Doctrine - Add default time stamp to entity like NOW()
Solution 1
Ok I found the solution:
- https://doctrine-orm.readthedocs.org/en/latest/reference/php-mapping.html?highlight=callback
- http://doctrine-orm.readthedocs.org/en/latest/reference/events.html#lifecycle-events
The prePersist
option is what I'm doing.
Make sure you define in the annotations
<?php
/** @Entity
* @HasLifecycleCallbacks
*/
class User
and here is the function example they offer
/**
* @PrePersist
*/
public function doStuffOnPrePersist()
{
$this->createdAt = date('Y-m-d H:i:s');
}
And if you're using ORM like I am
<?php
/** @ORM\Entity
* @ORM\HasLifecycleCallbacks
*/
class User
and here is the function example they offer
/**
* @ORM\PrePersist
*/
public function doStuffOnPrePersist()
{
$this->createdAt = date('Y-m-d H:i:s');
}
Solution 2
In my experience it is best to put everything in your Entities and not try to force your database to bypass the ORM.
<?php
namespace Phill\PaffordBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Stack
* @ORM\Table()
*/
class Stack
{
/**
* @var integer
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var \DateTime
* @ORM\Column(type="datetime")
*/
private $startDate;
public function __construct()
{
$this->startDate = new \DateTime();
}
}
Solution 3
In order to have exactly NOW()
you could extend Doctrine\DBAL\Types\DateTimeType
.
Other method:
class DateTimeNow
{
public function format()
{
return 'NOW()';
}
}
Then you can use $entity->setFieldDatetime(DateTimeNow())
instead of $entity->setFieldDatetime(new Datetime())
.
Note: The method format()
is automatically called by Doctrine.
Solution 4
Try this:
/**
* @var \DateTime
*
* @Column(name="created", type="datetime", nullable=false)
*/
private $created;
function __construct()
{
$this->created = new \DateTime();
}
The whatever $value
you assign to created
field, has to be able to handle this call:
$value->format('Y-m-d H:i:s');
See relevant Doctrine code line
Tested to work with Doctrine 2.5.4
Note: above works at creation time but not on update by default -- you have to manually set created
property to new \DateTime()
when you do an update or look into doStuffOnPrePersist
/** @PrePersist */
public function doStuffOnPrePersist()
{
$this->created = date('Y-m-d H:i:s');
}
Solution 5
You can use TimestampableEntity Trait for automatically create created_at and updated_at fields in you Entity;
First install doctrine-extensions;
composer require gedmo/doctrine-extensions
Secondly add trait into your Entity Class;
use Gedmo\Timestampable\Traits\TimestampableEntity;
/**
* @ORM\Entity(repositoryClass="App\Repository\ProjectRepository")
*/
class Project
{
use TimestampableEntity;
Phill Pafford
Love development with PHP/Symfony/PHPStorm, iOS, PostgreSQL, Linux flavor Ubuntu, jQuery/Mobile, Foundation CSS, GitFlow AVH and HTML5 Personal Projects are Crypto Currencies, Home Automation, Mobile development, SMS/MMS and DIY electronics via Make and Hack A Day https://keybase.io/phillpafford https://onename.com/phillpafford #bitcoin: https://www.coinbase.com/phillpafford #DogeCoin: D67fwUKwKQQeL9pdbZmbWcevuAYW8XPqyz
Updated on December 27, 2021Comments
-
Phill Pafford over 2 years
Following the Doctrine guidelines I understand how to set a default value for an Entity, but what if I wanted a date/time stamp?
My problem is my database has a default of NOW() on a field but when I use Doctrine to insert a record the values are null or blank but the rest of the insert happened.
Also since Doctrine says to declare the default as a const, this also creates a problem.
Suggestions?
-
Phill Pafford over 11 yearsThanks, Using PostgreSQL 9.x and when changing the DEFAULT value from now() to CURRENT_TIMESTAMP but it reverts back to now(). Also created a test table and set the datetime column to CURRENT_TIMESTAMP but also reverted to now(). Any other thoughts?
-
Mike Brant over 11 yearsSorry, didn't realize it was Postgres. I was giving commentary for MySQL which is more typically encountered by PHP users. Have added tag for PostgreSQL. I have updated my answer as well.
-
Phill Pafford over 11 yearssorry that didn;'t work either, DateTime issue when passing string NOW
-
Mike Brant over 11 yearsSo you are getting a PHP-level error from Doctrine when trying to use that value? If you are only using it for data insert purposes and aren't going to be reading from it, you might trick Doctrine be saying the field is a string. I haven't used Doctrine with Postgres, so I don't really know best approach in this case.
-
Phill Pafford almost 10 yearsI disagree, here is why: ORM can change, what if I do raw SQL, there are other reasons as well but this should be handled on the database side for at least data integrity
-
David Baucum almost 10 yearsThen it just depends on your needs. Often when using Doctrine it is the developer's intention to program to the ORM and just use the DB as the backend. If that is not the case then stuff will need to be pusehd to the DB, like you are suggesting. I think that for those who are looking to only interface with the ORM then this is the better solution.
-
Sejanus over 9 yearsIs there a way to achieve this without using the abomination that is php annotations?
-
Dennis over 8 years@Sejanus, yes, Doctrine has XML, YAML, and PHP annotations. See "Drivers" under docs.doctrine-project.org/projects/doctrine-orm/en/latest
-
Dennis over 8 yearsFrom the docs: "It should be noted that this event is only triggered on initial persist of an entity (i.e. it does not trigger on future updates)"
-
Thomas Landauer over 8 yearsWhere (i.e. in which file) is this code to be placed (in Symfony)? Thanks!
-
Alexandre over 8 years@ThomasLandauer I did it durty and had it directely in the file where I need to use it... But would be better to create a bundle in the vendor folder or something like this.
-
Thomas Landauer about 8 yearsThis answer is the only solution so far which uses the database server's time (rather than PHP's time). Here's why this is a good thing: stackoverflow.com/a/3705090/1668200
-
David Baucum about 8 yearsI think it is worth noting that both this solution and mine below are good solutions. There is an important distinction in how that work. In my solution the timestamp is created when the entity is first instantiated. In this solution the timestamp is set at the time it is persisted to the database.
-
David Baucum about 8 yearsI think it is worth noting that both this solution and @PhillPafford's above are good solutions. There is an important distinction in how that work. In my solution the timestamp is created when the entity is first instantiated. In this solution the timestamp is set at the time it is persisted to the database.
-
Dariux almost 8 yearsHow is this working for you? I get error: Error: Call to a member function format() on string which makes sense, because 'CURRENT_TIMESTAMP' is string :/
-
Dennis almost 8 yearshah, I get the same error! (I've been using this to read data only)
-
Dariux almost 8 yearsI used this in doStuffOnPrePersist() function
-
emix over 7 years"Don`t use magic hooks inside your entities" Marco Pivetta, author of the Doctrine
-
Dennis over 7 yearsDon't use it,... but if you must we program the
PrePersist
into Doctrine?:) -
Erce almost 5 yearsThis will work but the update will be done by doctrine in symfony layer. If you think that update should be done by db layer, than you need to find how to set
on update CURRENT_TIMESTAMP
. If you find also inform me as well :)