In a Symfony2 project, I have a Doctrine entity that has a datetime
field, called lastAccessed
. Also, the entity uses Timestampable on updatedAt
field.
namespace AppBundle\Entity;
use
Doctrine\ORM\Mapping as ORM,
Gedmo\Mapping\Annotation as Gedmo
;
class MyEntity {
/**
* @ORM\Column(type="datetime")
*/
private $lastAccessed;
/**
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="update")
*/
private $updatedAt;
}
I need to update the field lastAccessed
without also updating the updatedAt
field. How can I do that?
There is also an easy way (or more proper way) how to do it, just override listener.
first create interface which will be implemented by entity
interface TimestampableCancelInterface
{
public function isTimestampableCanceled(): bool;
}
than extend Timestampable listener and override updateField
.
this way we can disable all all events or with cancelTimestampable
define custom rules for cancellation based on entity state.
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();
}
}
implement interface. Most simple way is to just set property for this
private $isTimestampableCanceled = false;
public function cancelTimestampable(bool $cancel = true): void
{
$this->isTimestampableCanceled = $cancel;
}
public function isTimestampableCanceled():bool {
return $this->isTimestampableCanceled;
}
or define rules like you want
last thing is to not set default listener but ours. I'm using symfony so:
stof_doctrine_extensions:
orm:
default:
timestampable: true
class:
timestampable: <Namespace>\TimestampableListener
Than you can just do
$entity = new Entity;
$entity->cancelTimestampable(true)
$em->persist($entity);
$em->flush(); // and you will get constraint violation since createdAt is not null :D
This way can be timestamps disabled per single entity not for whole onFlush. Also custom behavior is easy to apply based on entity state.
I just stumbled upon this as well and came up with this solution:
public function disableTimestampable()
{
$eventManager = $this->getEntityManager()->getEventManager();
foreach ($eventManager->getListeners('onFlush') as $listener) {
if ($listener instanceof \Gedmo\Timestampable\TimestampableListener) {
$eventManager->removeEventSubscriber($listener);
break;
}
}
}
Something very similar can be used to disable the blamable behavior as well of course.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With