Buy

Activating Timestampable

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

Ok, let's add Timestampable! First, we need to activate it, which again, is described way down on the bundle's docs. Open config/packages/stof_doctrine_extensions.yaml, and add timestampable: true:

9 lines config/packages/stof_doctrine_extensions.yaml
... lines 1 - 2
stof_doctrine_extensions:
default_locale: en_US
orm:
default:
sluggable: true
timestampable: true

Second, your entity needs some annotations. For this, go back to the library's docs. Easy enough: we just need @Gedmo\Timestampable.

Back in our project, open Article and scroll down to find the new fields. Above createdAt, add @Timestampable() with on="create":

192 lines src/Entity/Article.php
... lines 1 - 10
class Article
{
... lines 13 - 55
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="create")
*/
private $createdAt;
... lines 61 - 190
}

Copy that, paste above updatedAt, and use on="update":

192 lines src/Entity/Article.php
... lines 1 - 10
class Article
{
... lines 13 - 61
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="update")
*/
private $updatedAt;
... lines 67 - 190
}

That should be it! Find your terminal, and reload the fixtures!

php bin/console doctrine:fixtures:load

No errors... but, let's make sure it's actually working. Run:

php bin/console doctrine:query:sql 'SELECT * FROM article'

Yes! They are set! And each time we update, the updated_at will change.

The TimestampableEntity Trait

I love Timestampable. Heck, I put it everywhere. And, fortunately, there is a shortcut! Yea, we did way too much work.

Check it out: completely delete the createdAt and updatedAt fields that we so-carefully added. And, remove the getter and setter methods at the bottom too:

192 lines src/Entity/Article.php
... lines 1 - 10
class Article
{
... lines 13 - 55
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="create")
*/
private $createdAt;
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="update")
*/
private $updatedAt;
... lines 67 - 167
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(?\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updatedAt;
}
public function setUpdatedAt(?\DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
}

But now, all the way on top, add use TimestampableEntity:

159 lines src/Entity/Article.php
... lines 1 - 6
use Gedmo\Timestampable\Traits\TimestampableEntity;
... lines 8 - 11
class Article
{
use TimestampableEntity;
... lines 15 - 157
}

Yea! Hold Command or Ctrl and click to see that. Awesome: this contains the exact same code that we had before! If you want Timestampable, just use this trait, generate a migration and... done!

And, talking about migrations, there could be some slight column differences between these columns and the original ones we created. Let's check that. Run:

php bin/console make:migration

No database changes were detected

Cool! The fields in the trait are identical to what we had before. That means that we can already test things with:

php bin/console doctrine:fixtures:load

Thank you TimestampableEntity!

Up Next: Relations!

Ok guys! I hope you are loving Doctrine! We just got a lot of functionality fast. We have magic - like Timestampable & Sluggable - rich data fixtures, and a rocking migration system.

One thing that we have not talked about yet is production config. And... that's because it's already setup. The Doctrine recipe came with its own config/packages/prod/doctrine.yaml config file, which makes sure that anything that can be cached easily, is cached:

32 lines config/packages/prod/doctrine.yaml
doctrine:
orm:
metadata_cache_driver:
type: service
id: doctrine.system_cache_provider
query_cache_driver:
type: service
id: doctrine.system_cache_provider
result_cache_driver:
type: service
id: doctrine.result_cache_provider
services:
doctrine.result_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '@doctrine.result_cache_pool'
doctrine.system_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '@doctrine.system_cache_pool'
framework:
cache:
pools:
doctrine.result_cache_pool:
adapter: cache.app
doctrine.system_cache_pool:
adapter: cache.system

This means you get nice performance, out-of-the-box.

The other huge topic that we have not talked about yet is Doctrine relations. But, we should totally talk about those - they're awesome! So let's do that in our next tutorial, with foreign keys, join queries and high-fives so that we can create a really rich database.

Alright guys, seeya next time.

Leave a comment!

  • 2018-07-10 Diego Aguiar

    Hey Scottie Gutman

    Right now we are delivering the ReactJS tutorial and after that, we will release Symfony4 security tutorial. So, if you are looking for something specific to Symfony forms, then watching our Symfony3 tutorials about that topic would be a good idea, and anyways, it didn't change dramatically :)

    Cheers!

  • 2018-07-10 Scottie Gutman

    I have used doctrine for years now and I keep learning new things that make it so much better. Thanks.

    May I ask, when will the next course come out? Should I review the Symfony 3 Forms: Build, Render & Conquer! for the latest info on forms or is there something better to review?

  • 2018-06-13 Gilles Hoarau

    Thanks! Looking forward to learn even more and high five an ice cream!