You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用TimestampableEntity trait的实体执行PUT操作失败

问题:API Platform中Gedmo Timestampable PUT操作触发created_at非空约束错误

全新安装API Platform v3.2.7环境,使用Gedmo\Timestampable\Traits\TimestampableEntity trait实现自动时间戳,POST创建实体正常,但执行PUT更新操作时失败,报错:

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

实体代码(Greeting示例)

<?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;
    }
}

services.yaml配置

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' }

使用版本

  • Symfony 6.4.1
  • Doctrine 2.12
  • Gedmo 3.14

解决方案

原因分析

PUT操作时,API Platform默认会按请求体内容完全替换实体对象,若请求未传递created_at字段,该值会被设为null。而Gedmo的Timestampable监听器仅在创建时填充created_at,更新操作只处理updated_at,最终触发数据库非空约束。

解决步骤

  1. 禁止API修改created_at字段
    在实体中通过注解排除createdAt的可写权限,避免请求覆盖该字段:

    #[ApiResource(
        denormalizationContext: ['exclude' => ['createdAt', 'updatedAt']]
    )]
    #[ORM\Entity]
    class Greeting
    {
        use TimestampableEntity;
        // 其他原有代码...
    }
    

    或覆写Trait中的属性添加单独注解:

    #[ORM\Column(type: 'datetime_immutable')]
    #[ApiProperty(writable: false)]
    private \DateTimeInterface $createdAt;
    
    use TimestampableEntity {
        TimestampableEntity::__construct as private __traitConstruct;
    }
    
    public function __construct()
    {
        $this->__traitConstruct();
    }
    
  2. 完善Doctrine监听器配置
    为Timestampable监听器添加preUpdate事件标签,确保更新逻辑正常触发:

    gedmo.listener.timestampable:
        class: Gedmo\Timestampable\TimestampableListener
        tags:
            - { name: doctrine.event_listener, event: 'prePersist' }
            - { name: doctrine.event_listener, event: 'preUpdate' }
            - { name: doctrine.event_listener, event: 'onFlush' }
            - { name: doctrine.event_listener, event: 'loadClassMetadata' }
    
  3. 数据库字段兜底配置
    为created_at字段添加数据库层面的默认值,避免极端情况下的空值问题:

    #[ORM\Column(type: 'datetime_immutable', nullable: false, options: ['default' => 'CURRENT_TIMESTAMP'])]
    

内容的提问来源于stack exchange,提问作者Matías Cánepa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 11:07:38