It is possible to automatically set created_at
and updated_at
column values on entity update. In order to achieve that you have to write a
custom mapper implementation to automatically register these values in entity commands.
The simplest mapper will look like:
use Cycle\ORM\Mapper\Mapper;
use Cycle\ORM\Heap\Node;
use Cycle\ORM\Heap\State;
use Cycle\ORM\Command\Database\Update;
use Cycle\ORM\Command\ContextCarrierInterface;
class TimestampedMapper extends Mapper
{
public function queueCreate($entity, Node $node, State $state): ContextCarrierInterface
{
$cmd = parent::queueCreate($entity, $node, $state);
$state->register('created_at', new \DateTimeImmutable(), true);
$cmd->register('created_at', new \DateTimeImmutable(), true);
$state->register('updated_at', new \DateTimeImmutable(), true);
$cmd->register('updated_at', new \DateTimeImmutable(), true);
return $cmd;
}
public function queueUpdate($entity, Node $node, State $state): ContextCarrierInterface
{
/** @var Update $cmd */
$cmd = parent::queueUpdate($entity, $node, $state);
$state->register('updated_at', new \DateTimeImmutable(), true);
$cmd->registerAppendix('updated_at', new \DateTimeImmutable());
return $cmd;
}
}
While we can set column values directly in the
Insert
command, we have to use the alternative methodregisterAppendix
forUpdate
. This method will only push changes to the database if any other entity field has changes (for example if entity FK has been updated through the relation).
You can use the annotated entities extension to automatically declare the needed columns from inside your mapper:
use Cycle\ORM\Mapper\Mapper;
use Cycle\ORM\Heap\Node;
use Cycle\ORM\Heap\State;
use Cycle\ORM\Command\Database\Update;
use Cycle\ORM\Command\ContextCarrierInterface;
/**
* @Table(
* columns={"created_at": @Column(type="datetime"), "updated_at": @Column(type="datetime")},
* )
*/
class TimestampedMapper extends Mapper
{
public function queueCreate($entity, Node $node, State $state): ContextCarrierInterface
{
$cmd = parent::queueCreate($entity, $node, $state);
$state->register('created_at', new \DateTimeImmutable(), true);
$cmd->register('created_at', new \DateTimeImmutable(), true);
$state->register('updated_at', new \DateTimeImmutable(), true);
$cmd->register('updated_at', new \DateTimeImmutable(), true);
return $cmd;
}
public function queueUpdate($entity, Node $node, State $state): ContextCarrierInterface
{
/** @var Update $cmd */
$cmd = parent::queueUpdate($entity, $node, $state);
$state->register('updated_at', new \DateTimeImmutable(), true);
$cmd->registerAppendix('updated_at', new \DateTimeImmutable());
return $cmd;
}
}
Associate your entity with the newly created mapper in order to register these columns on schema update:
/** @Entity(mapper="TimestampedMapper") */
class User
{
// ...
}
You can use one mapper for multiple entities.