使用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,最终触发数据库非空约束。
解决步骤
禁止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(); }完善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' }数据库字段兜底配置
为created_at字段添加数据库层面的默认值,避免极端情况下的空值问题:#[ORM\Column(type: 'datetime_immutable', nullable: false, options: ['default' => 'CURRENT_TIMESTAMP'])]
内容的提问来源于stack exchange,提问作者Matías Cánepa
相关产品推荐
相关产品推荐

