还有一种简单的方法(或更正确的方法)如何做到这一点,只需覆盖侦听器。
首先创建将由实体实现的接口
interface TimestampableCancelInterface
{
public function isTimestampableCanceled(): bool;
}
扩展 Timestampable 侦听器并覆盖 updateField。
这样我们就可以禁用所有事件,或者使用cancelTimestampable根据实体状态定义自定义取消规则。
class TimestampableListener extends \Gedmo\Timestampable\TimestampableListener
{
protected function updateField($object, $eventAdapter, $meta, $field)
{
/** @var \Doctrine\Orm\Mapping\ClassMetadata $meta */
$property = $meta->getReflectionProperty($field);
$newValue = $this->getFieldValue($meta, $field, $eventAdapter);
if (!$this->isTimestampableCanceled($object)) {
$property->setValue($object, $newValue);
}
}
private function isTimestampableCanceled($object): bool
{
if(!$object instanceof TimestampableCancelInterface){
return false;
}
return $object->isTimestampableCanceled();
}
}
实现接口。最简单的方法是为此设置属性
private $isTimestampableCanceled = false;
public function cancelTimestampable(bool $cancel = true): void
{
$this->isTimestampableCanceled = $cancel;
}
public function isTimestampableCanceled():bool {
return $this->isTimestampableCanceled;
}
或根据需要定义规则
最后一件事是不设置默认侦听器,而是设置我们的侦听器。
我正在使用 symfony:
stof_doctrine_extensions:
orm:
default:
timestampable: true
class:
timestampable: <Namespace>\TimestampableListener
你可以做到的
$entity = new Entity;
$entity->cancelTimestampable(true)
$em->persist($entity);
$em->flush(); // and you will get constraint violation since createdAt is not null :D
这种方式可以禁用单个实体的时间戳,而不是整个 onFlush。此外,自定义行为也很容易根据实体状态应用。