I have Product entity with many-to-one to Category entity. I need store Product in session. First of all i try to implement \Serializable interface on Product. How should i serialize my related Category entity? Should i also implement \Serializable interface?
I read, that serialization in doctrine is very pain operation and i think about this:
Can we get raw values from entity? Exactly that data, which stored in database. If we can get this values, we can store it anywhere and recreate object!
I read doctrine2 code and find method Doctrine\ORM\Internal\Hydration\ObjectHydrator:hydrateRowData but it's protected. Is there any public api for doing this?
I just copypaste and integrate some code from BasicEntityPersister and it seems to work.
    $product = $productsRepository->find($id);
    if (!$product) {
        throw $this->createNotFoundException('No product found for id ' . $id);
    }
    $uow = $em->getUnitOfWork();
    $entityPersister = $uow->getEntityPersister(get_class($product));
    $classMetadata = $entityPersister->getClassMetadata();
    $originalData = $uow->getOriginalEntityData($product);
    $result = array();
    foreach ($originalData as $field => $value) {
        if (isset($classMetadata->associationMappings[$field])) {
            $assoc = $classMetadata->associationMappings[$field];
            // Only owning side of x-1 associations can have a FK column.
            if ( ! $assoc['isOwningSide'] || ! ($assoc['type'] & \Doctrine\ORM\Mapping\ClassMetadata::TO_ONE)) {
                continue;
            }
            if ($value !== null) {
                $newValId = $uow->getEntityIdentifier($value);
            }
            $targetClass = $em->getClassMetadata($assoc['targetEntity']);
            $owningTable = $entityPersister->getOwningTable($field);
            foreach ($assoc['joinColumns'] as $joinColumn) {
                $sourceColumn = $joinColumn['name'];
                $targetColumn = $joinColumn['referencedColumnName'];
                if ($value === null) {
                    $result[$owningTable][$sourceColumn] = null;
                } else if ($targetClass->containsForeignIdentifier) {
                    $result[$owningTable][$sourceColumn] = $newValId[$targetClass->getFieldForColumn($targetColumn)];
                } else {
                    $result[$owningTable][$sourceColumn] = $newValId[$targetClass->fieldNames[$targetColumn]];
                }
            }
        } elseif (isset($classMetadata->columnNames[$field])) {
            $columnName = $classMetadata->columnNames[$field];
            $result[$entityPersister->getOwningTable($field)][$columnName] = $value;
        }
    }
    print_r($result);
In $result we have raw values. Now we need way how to create object by this array
<?php
namespace Acme\ServiceBundle\Services;
use Doctrine\ORM\EntityManager;
class EntitySerializer
{
    protected $em;
    public function __construct(EntityManager $em)
    {
        $this->em = $em;
    }
    public function serialize($entity)
    {
        $className = get_class($entity);
        $uow = $this->em->getUnitOfWork();
        $entityPersister = $uow->getEntityPersister($className);
        $classMetadata = $entityPersister->getClassMetadata();
        $result = array();
        foreach ($uow->getOriginalEntityData($entity) as $field => $value) {
            if (isset($classMetadata->associationMappings[$field])) {
                $assoc = $classMetadata->associationMappings[$field];
                // Only owning side of x-1 associations can have a FK column.
                if ( ! $assoc['isOwningSide'] || ! ($assoc['type'] & \Doctrine\ORM\Mapping\ClassMetadata::TO_ONE)) {
                    continue;
                }
                if ($value !== null) {
                    $newValId = $uow->getEntityIdentifier($value);
                }
                $targetClass = $this->em->getClassMetadata($assoc['targetEntity']);
                $owningTable = $entityPersister->getOwningTable($field);
                foreach ($assoc['joinColumns'] as $joinColumn) {
                    $sourceColumn = $joinColumn['name'];
                    $targetColumn = $joinColumn['referencedColumnName'];
                    if ($value === null) {
                        $result[$sourceColumn] = null;
                    } else if ($targetClass->containsForeignIdentifier) {
                        $result[$sourceColumn] = $newValId[$targetClass->getFieldForColumn($targetColumn)];
                    } else {
                        $result[$sourceColumn] = $newValId[$targetClass->fieldNames[$targetColumn]];
                    }
                }
            } elseif (isset($classMetadata->columnNames[$field])) {
                $columnName = $classMetadata->columnNames[$field];
                $result[$columnName] = $value;
            }
        }
        return array($className, $result);
    }
    public function deserialize(Array $data)
    {
        list($class, $result) = $data;
        $uow = $this->em->getUnitOfWork();
        return $uow->createEntity($class, $result);
    }
}
                        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