Search code examples
symfonydoctrine-ormapi-platform.com

Entity with Timestampable properties is not working


I'm on a fresh install of API Platform (v3.2.7) and I'm trying to implement Gedmo's Timestampable on the example Greeting entity. I first tried using attributes

<?php

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\DBAL\Types\Types;

/**
 * This is a dummy entity. Remove it!
 */
#[ApiResource]
#[ORM\Entity]
class Greeting
{
    /**
     * The entity ID
     */
    #[ORM\Id]
    #[ORM\Column(type: 'integer')]
    #[ORM\GeneratedValue]
    private ?int $id = null;

    /**
     * A nice person
     */
    #[ORM\Column]
    #[Assert\NotBlank]
    public string $name = '';

    public function getId(): ?int
    {
        return $this->id;
    }

    #[Gedmo\Timestampable(on: 'create')]
    #[ORM\Column(type: Types::DATETIME_MUTABLE)]
    protected $createdAt;

    #[Gedmo\Timestampable(on: 'update')]
    #[ORM\Column(type: Types::DATETIME_MUTABLE)]
    protected $updatedAt;
}

But that didn't work, so I've tried using trait

<?php

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Gedmo\Timestampable\Traits\TimestampableEntity;

/**
 * This is a dummy entity. Remove it!
 */
#[ApiResource]
#[ORM\Entity]
class Greeting
{
    use TimestampableEntity;
    /**
     * The entity ID
     */
    #[ORM\Id]
    #[ORM\Column(type: 'integer')]
    #[ORM\GeneratedValue]
    private ?int $id = null;

    /**
     * A nice person
     */
    #[ORM\Column]
    #[Assert\NotBlank]
    public string $name = '';

    public function getId(): ?int
    {
        return $this->id;
    }
}

In both cases the error is:

An exception occurred while executing a query: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'created_at' cannot be null

I've also tried this that worked for me in the past

# config/services.yaml
    gedmo.listener.timestampable:
        class: Gedmo\Timestampable\TimestampableListener
        tags:
            - { name: doctrine.event_subscriber, connection: default }
        calls:
            - [ setAnnotationReader, [ '@annotation_reader' ] ]

and the error is:

The service "gedmo.listener.timestampable" has a dependency on a non-existent service "annotation_reader"

I dont't if it has to be with the deprecation of Doctrine Lifecycle Subscribers in symfony 6.3

EDIT I see this in profiler (doctrine), so I guess the 2 timestamps are set to NULL instead of the correct value

enter image description here


Solution

  • I finally got it working. I had to change the way the service is registered

    gedmo.listener.timestampable:
        class: Gedmo\Timestampable\TimestampableListener
        tags:
            - { name: doctrine.event_listener, event: 'prePersist' }
            - { name: doctrine.event_listener, event: 'onFlush' }
            - { name: doctrine.event_listener, event: 'loadClassMetadata' }
    

    Without setting

        calls:
            - [ setAnnotationReader, [ '@annotation_reader' ] ]
    

    And the class with trait

    <?php
    
    namespace App\Entity;
    
    use ApiPlatform\Metadata\ApiResource;
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Component\Validator\Constraints as Assert;
    
    use Gedmo\Timestampable\Traits\TimestampableEntity;
    
    #[ApiResource]
    #[ORM\Entity]
    class Greeting
    {
        use TimestampableEntity;
    
        #[ORM\Id]
        #[ORM\Column(type: "integer")]
        #[ORM\GeneratedValue]
        private ?int $id = null;
    
        #[ORM\Column]
        #[Assert\NotBlank]
        public string $name = "";
    
        public function getId(): ?int
        {
            return $this->id;
        }
    }
    

    One more piece of information: in order to make it work as I used to only API Platform up to version 3.0.9 is suitable. Later versions no longer work with the services configuration. (I guess it has to do with the event subscriber deprecation)

    Now I have another issue with PUT request but that's for another post...