PHP Doctrine: How to add created_at and updated_at columns

Updated: January 13, 2024 By: Guest Contributor Post a comment

Introduction

In modern web development, tracking when database records are created and updated can be incredibly valuable. This metadata allows developers to keep records of changes, analyze data over time, and add functionality related to the timing of records. In applications that use PHP and Doctrine ORM, adding created_at and updated_at columns is a common task. This tutorial will guide you through adding such timestamp columns to your Doctrine entities in a step-by-step fashion.

Before we start, make sure you have a working PHP environment with Doctrine ORM installed. If you’re using Symfony, Doctrine likely came as part of the standard installation.

Setting Up Timestamp Columns

First, let’s define a basic entity with Doctrine annotations to include created_at and updated_at columns:

use Doctrine\ORM\Mapping as ORM; 
/** 
 * @ORM\Entity 
 * @ORM\HasLifecycleCallbacks 
 */ 
class Article { 
    /** 
     * @ORM\Column(type="datetime") 
     * @var \DateTime 
     */ 
    protected $created_at; 
    /** 
     * @ORM\Column(type="datetime") 
     * @var \DateTime 
     */ 
    protected $updated_at; 

    /** 
     * @ORM\PrePersist 
     */ 
    public function onPrePersist() { 
        $this->created_at = new \DateTime("now"); 
        if (!$this->updated_at) { 
            $this->updated_at = new \DateTime("now"); 
        } 
    } 

    /** 
     * @ORM\PreUpdate 
     */ 
    public function onPreUpdate() { 
        $this->updated_at = new \DateTime("now"); 
    } 

    // ... Other fields and methods 
}

This code snippet creates a new entity Article with created_at and updated_at fields. The @ORM\HasLifecycleCallbacks annotation at the class level indicates that this entity is subscribing to Doctrine’s event system. By placing @ORM\PrePersist and @ORM\PreUpdate on methods, we instruct Doctrine to call them right before the entity is first persisted and before any update operation respectively. Each method sets the datetime based on the current time.

The above code will create columns in the database that store datetime information, matching the time an Article is first saved or subsequently updated. However, this is just the first step. As your application grows, you might need to refine and automate this process further.

Using Doctrine Extensions for Timestampable Behavior

Let’s proceed to more advanced usage by integrating the Gedmo Doctrine extension for Timestampable behavior. This extension automates the process of setting created_at and updated_at fields.

Firstly, install the Gedmo Doctrine extensions using Composer:

composer require gedmo/doctrine-extensions

Next, configure the listener in your bootstrap or application configuration:

// Assuming you have the EntityManager $em 
use Gedmo\Timestampable\TimestampableListener; 
use Doctrine\Common\EventManager; 

$timestampableListener = new TimestampableListener(); 
$em->getEventManager()->addEventSubscriber($timestampableListener);

Then, update the entity to leverage the Timestampable functionality:

use Gedmo\Mapping\Annotation as Gedmo; 
use Doctrine\ORM\Mapping as ORM; 

/** 
 * @ORM\Entity 
 * @Gedmo\Timestampable(on="create") 
 */ 
class Article { 
    /** 
     * @Gedmo\Timestampable(on="create") 
     * @ORM\Column(type="datetime") 
     * @var \DateTime 
     */ 
    protected $created_at; 

    /** 
     * @Gedmo\Timestampable(on="update") 
     * @ORM\Column(type="datetime") 
     * @var \DateTime 
     */ 
    protected $updated_at;
    // ... Other fields and methods 
}

By using the @Gedmo\Timestampable annotation, you indicate that the timestamp should be updated automatically upon creation or update, without the explicit need for lifecycle event methods.

Whenever you create a new entity or update an existing one, Doctrine now takes care of setting these timestamps for you. For a Symfony application, this integration would also require you to register the extension in your service configuration.

Handling Migrations

If you’re managing your database schema through Doctrine migrations, ensure to generate a new migration after adding created_at and updated_at fields to any entity:

php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate

This commands create a new migration class with the necessary SQL to add the new columns and then execute the migration to update the database schema.

Conclusion

Generated timestamps for created_at and updated_at columns provide an automated way to handle record metadata related to date and time. Whether you are just starting with Doctrine events or integrating more sophisticated extensions, having these timestamps can give you insights, better data management, and a robust history of your records.