orm icon indicating copy to clipboard operation
orm copied to clipboard

After persist with custom extract don't typecast properties.

Open vjik opened this issue 5 years ago • 2 comments

Entity:

final class Entity
{
    /** @var int */
    public $id;

    /** @var DateTimeImmutable */
    public $createDate;
}

Schema:

 'entity' => [
        Schema::ENTITY => Entity::class,
        Schema::TABLE => 'cmt_comment',
        Schema::PRIMARY_KEY => 'id',
        Schema::MAPPER => EntityMapper::class,
        Schema::COLUMNS => [
            'id' => 'id',
            'createDate' => 'create_date',
        ],
        Schema::TYPECAST => [
            'id' => 'int',
            'createDate' => function ($value, DatabaseInterface $db) {
                return (new DateTimeImmutable())->setTimestamp((int)$value);
            },
        ],
        Schema::RELATIONS => [],
    ],

Mapper:

final class EntityMapper extends Mapper
{
    public function extract($entity): array
    {
        $data = parent::extract($entity);
        $data['createDate'] = $data['createDate'] === null ? null : (string)$data['createDate']->getTimestamp();
        return $data;
    }
}

Code:

$entity = $orm->getRepository('entity')->findByPK(1);
$entity->createDate; // DateTimeImmutable
(new Transaction($orm))->persist($entity)->run();
$entity->createDate; // string

Get form DB - OK. Save to DB - OK.

But after persist createDate is string (should be DateTimeImmutable).


I resolve problem so: remove typecast from schema and add custom hydrate to mapper:

final class EntityMapper extends Mapper
{
    public function extract($entity): array
    {
        $data = parent::extract($entity);
        $data['createDate'] = $data['createDate'] === null ? null : (string)$data['createDate']->getTimestamp();
        return $data;
    }
    public function hydrate($entity, array $data)
    {
        if (array_key_exists('createDate', $data) && is_string($data['createDate'])) {
            $data['createDate'] = (new DateTimeImmutable())->setTimestamp((int)$data['createDate']);
        }
        return parent::hydrate($entity, $data);
    }
}

But I think this not beautiful solution...

vjik avatar Oct 10 '20 17:10 vjik

We will have to alter logic of post-sync entity update to handle it nicely. Can you stick to ValueInterface in a meantime, it's essentially doing the same thing. https://cycle-orm.dev/docs/advanced-column-wrappers#raw-values

wolfy-j avatar Oct 14 '20 10:10 wolfy-j

We will have to alter logic of post-sync entity update to handle it nicely. Can you stick to ValueInterface in a meantime, it's essentially doing the same thing.

No, better use custom mapper with extract and hydrate.

I will wait for implementation. Thank you!

vjik avatar Oct 14 '20 10:10 vjik