Automatic values for updated_at, created_at in Doctrine
PhpDoctrine OrmPhp Problem Overview
I want to make fields updated_at
and created_at
in my Doctrine entities to update automatically.
In Ruby on Rails models there are 2 fields: updated_at
and created_at
.
Description can be found here: http://guides.rubyonrails.org/migrations.html#migration-overview: > The timestamps macro adds two columns, created_at and updated_at. These special columns are automatically managed by Active Record if they exist.
Can I enable similar functionality in Doctrine 2?
Php Solutions
Solution 1 - Php
- You can call
$this->setCreatedAt(new \DateTime())
in__construct
method. - You can use Life Cycle Callbacks
/**
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function updatedTimestamps(): void
{
$this->setUpdatedAt(new \DateTime('now'));
if ($this->getCreatedAt() === null) {
$this->setCreatedAt(new \DateTime('now'));
}
}
And don't forget to add into entity class notation:
@ORM\HasLifecycleCallbacks
Solution 2 - Php
This is another option if you would ever want to handle them separately.
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="person")
* @ORM\HasLifecycleCallbacks
*/
class Person
{
..........
/**
* @var datetime $created
*
* @ORM\Column(type="datetime")
*/
protected $created;
/**
* @var datetime $updated
*
* @ORM\Column(type="datetime", nullable = true)
*/
protected $updated;
/**
* Gets triggered only on insert
* @ORM\PrePersist
*/
public function onPrePersist()
{
$this->created = new \DateTime("now");
}
/**
* Gets triggered every time on update
* @ORM\PreUpdate
*/
public function onPreUpdate()
{
$this->updated = new \DateTime("now");
}
..........
}
Solution 3 - Php
The most convinient solution for me is Timestampable
feature of StofDoctrineExtensionsBundle.
Simple configuration and later you are able to make fields createdAt
and updatedAt
of Entity
filled out automatically by adding two simple annotations
like:
@Gedmo\Mapping\Annotation\Timestampable(on="create")
and/or
@Gedmo\Mapping\Annotation\Timestampable(on="update")
e.g.
/**
* @var \DateTime
* @Gedmo\Mapping\Annotation\Timestampable(on="create")
* @Doctrine\ORM\Mapping\Column(type="datetime")
*/
protected $createdAt;
/**
* @var \DateTime
* @Gedmo\Mapping\Annotation\Timestampable(on="update")
* @Doctrine\ORM\Mapping\Column(type="datetime")
*/
protected $updatedAt;
Without any redundant code in pure PHP
.
Solution 4 - Php
You can implement it as a trait as well - like this:
<?php
namespace App\Entity\Traits;
use DateTime;
use DateTimeInterface;
use Exception;
/**
* Trait TimeStampableTrait
* @package App\Entity\Trait
*/
trait TimeStampableTrait
{
/**
* @ORM\Column(type="datetime")
*/
private $createdAt;
/**
* @ORM\Column(type="datetime")
*/
private $updatedAt;
/**
* @return DateTimeInterface|null
* @throws Exception
*/
public function getCreatedAt(): ?DateTimeInterface
{
return $this->createdAt ?? new DateTime();
}
/**
* @param DateTimeInterface $createdAt
* @return $this
*/
public function setCreatedAt(DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
/**
* @return DateTimeInterface|null
*/
public function getUpdatedAt(): ?DateTimeInterface
{
return $this->updatedAt ?? new DateTime();
}
/**
* @param DateTimeInterface $updatedAt
* @return $this
*/
public function setUpdatedAt(DateTimeInterface $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* @ORM\PrePersist()
* @ORM\PreUpdate()
*/
public function updateTimestamps(): void
{
$now = new DateTime();
$this->setUpdatedAt($now);
if ($this->getId() === null) {
$this->setCreatedAt($now);
}
}
}
Add this trait to your entity (and don't forget @ORM\HasLifecycleCallbacks()
notation):
<?php
namespace App\Entity;
use App\Entity\Traits\TimeStampableTrait;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\MyEntityRepository")
* @ORM\HasLifecycleCallbacks()
*/
class MyEntity
{
use TimeStampableTrait;
}
Solution 5 - Php
I would suggest using timestampable trait
https://symfonycasts.com/screencast/symfony4-doctrine/timestampable
use Gedmo\Timestampable\Traits\TimestampableEntity;
class Article
{
use TimestampableEntity;
}
will add all appropriate functionality automatically