2017-02-05 5 views
4

Я использую JMSSerializer для десериализации запроса JSON, и у меня возникают проблемы с отношениями ManyToOne. Я хотел бы десериализовать объект отношения из указанного идентификатора. Пример:JMSSerializer десериализует объект по id

Class Game { 


/** 
* @var Team 
* 
* @ORM\ManyToOne(targetEntity="Team") 
* @ORM\JoinColumn(name="home_team_id", referencedColumnName="id") 
* @JMSSerializer\SerializedName("home") 
*/ 
private $homeTeam; 

/** 
* @ORM\ManyToOne(targetEntity="Team") 
* @ORM\JoinColumn(name="visitor_team_id", referencedColumnName="id") 
* @JMSSerializer\SerializedName("visitor") 
*/ 
private $visitorTeam; 
} 

Так что, когда я получаю это Json

{ "домой": "ID1", "посетитель": "id2"}

Получить соответствующие объекты. Любые облака? я не могу понять его

Спасибо заранее

ответ

4

Пользовательские serializer handler позволяет сделать это.

Сначала вам необходимо создать свой собственный обработчик сериализации. Что-то вроде этого:

<?php 

namespace AppBundle\Serializer\Handler; 

use Doctrine\ORM\EntityManagerInterface; 
use Symfony\Bridge\Doctrine\RegistryInterface; 
use JMS\Serializer\Context; 
use JMS\Serializer\Exception\InvalidArgumentException; 
use JMS\Serializer\GenericDeserializationVisitor; 
use JMS\Serializer\Handler\SubscribingHandlerInterface; 
use JMS\Serializer\VisitorInterface; 
use JMS\Serializer\GraphNavigator; 

class EntityHandler implements SubscribingHandlerInterface 
{ 
    /** 
    * @var RegistryInterface 
    */ 
    protected $registry; 

    /** 
    * @return array 
    */ 
    public static function getSubscribingMethods() 
    { 
     $methods = []; 

     foreach (['json', 'xml', 'yml'] as $format) { 
      $methods[] = [ 
       'type' => 'Entity', 
       'direction' => GraphNavigator::DIRECTION_DESERIALIZATION, 
       'format' => $format, 
       'method' => 'deserializeEntity', 
      ]; 

      $methods[] = [ 
       'type' => 'Entity', 
       'format' => $format, 
       'direction' => GraphNavigator::DIRECTION_SERIALIZATION, 
       'method' => 'serializeEntity', 
      ]; 
     } 

     return $methods; 
    } 

    /** 
    * EntityHandler constructor. 
    * @param RegistryInterface $registry 
    */ 
    public function __construct(RegistryInterface $registry) 
    { 
     $this->registry = $registry; 
    } 

    /** 
    * @param VisitorInterface $visitor 
    * @param $entity 
    * @param array $type 
    * @param Context $context 
    * @return mixed 
    */ 
    public function serializeEntity(VisitorInterface $visitor, $entity, array $type, Context $context) 
    { 
     $entityClass = $this->getEntityClassFromParameters($type['params']); 
     if (!$entity instanceof $entityClass) { 
      throw new InvalidArgumentException(
       sprintf("Entity class '%s' was expected, but '%s' got", $entityClass, get_class($entity)) 
      ); 
     } 

     $entityManager = $this->getEntityManager($entityClass); 
     $primaryKeyValues = $entityManager->getClassMetadata($entityClass)->getIdentifierValues($entity); 
     if (count($primaryKeyValues) > 1) { 
      throw new InvalidArgumentException(
       sprintf("Composite primary keys does'nt supported now (found in class '%s')", $entityClass) 
      ); 
     } 
     if (!count($primaryKeyValues)) { 
      throw new InvalidArgumentException(
       sprintf("No primary keys found for entity '%s')", $entityClass) 
      ); 
     } 

     $id = array_shift($primaryKeyValues); 
     if (is_int($id) || is_string($id)) { 
      return $visitor->visitString($id, $type, $context); 
     } else { 
      throw new InvalidArgumentException(
       sprintf(
        "Invalid primary key type for entity '%s' (only integer or string are supported", 
        $entityClass 
       ) 
      ); 
     } 
    } 

    /** 
    * @param GenericDeserializationVisitor $visitor 
    * @param string $id 
    * @param array $type 
    */ 
    public function deserializeEntity(GenericDeserializationVisitor $visitor, $id, array $type) 
    { 
     if (null === $id) { 
      return null; 
     } 

     if (!(is_array($type) && isset($type['params']) && is_array($type['params']) && isset($type['params']['0']))) { 
      return null; 
     } 

     $entityClass = $type['params'][0]['name']; 
     $entityManager = $this->getEntityManager($entityClass); 

     return $entityManager->getRepository($entityClass)->find($id); 
    } 

    /** 
    * @param array $parameters 
    * @return string 
    */ 
    protected function getEntityClassFromParameters(array $parameters) 
    { 
     if (!(isset($parameters[0]) && is_array($parameters[0]) && isset($parameters[0]['name']))) { 
      throw new InvalidArgumentException('Entity class is not defined'); 
     } 

     if (!class_exists($parameters[0]['name'])) { 
      throw new InvalidArgumentException(sprintf("Entity class '%s' is not found", $parameters[0]['name'])); 
     } 

     return $parameters[0]['name']; 
    } 

    /** 
    * @param string $entityClass 
    * @return EntityManagerInterface 
    */ 
    protected function getEntityManager($entityClass) 
    { 
     $entityManager = $this->registry->getEntityManagerForClass($entityClass); 
     if (!$entityManager) { 
      throw new InvalidArgumentException(
       sprintf("Entity class '%s' is not mannaged by Doctrine", $entityClass) 
      ); 
     } 

     return $entityManager; 
    } 
} 

Затем вы должны зарегистрировать его в своем конфигурационном файле службы. Если вы используете YAML, то это будет что-то вроде этого:

custom_serializer_handle: 
    class: AppBundle\Serializer\Handler\EntityHandler 
    arguments: ['@doctrine'] 
    tags: 
     - {name: 'jms_serializer.subscribing_handler'} 

В вашей организации, определить JMSSerializer Type аннотацию

/** 
* @var Team 
* * @ORM\ManyToOne(targetEntity="Team") 
* @ORM\JoinColumn(name="home_team_id", referencedColumnName="id") 
* @JMSSerializer\SerializedName("home") 
* @JMSSerializer\Type("Entity<AppBundle\Entity\Team>") 
* List item 
*/ 
private $homeTeam; 

Не забудьте четко кэши. Вот и все.

+0

Это работает, но если $ homeTeam также имеет аннотацию @groups, это игнорируется, даже если группа является открытой. Любая идея почему? – theva

Смежные вопросы