2017-08-01 25 views
0

我試圖序列化屬性,它是一個原則標準:JMS VirtualProperty與參數和用戶定製的監聽/用戶

public function getUserResults(User $user) 
{ 
    $criteria = Criteria::create() 
     ->where(Criteria::expr()->eq('user', $user)) 
    ; 

    return $this->getResults()->matching($criteria); 
} 

我不能使用@VirtualProperty,因爲它需要一個自變量,所以我實現了自定義的用戶一我種下這個帖子:

https://stackoverflow.com/a/44244747

<?php 

namespace AppBundle\Serializer; 

use JMS\Serializer\EventDispatcher\EventSubscriberInterface; 
use JMS\Serializer\EventDispatcher\PreSerializeEvent; 
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; 
use JMS\Serializer\EventDispatcher\ObjectEvent; 

class ExerciseSubscriber implements EventSubscriberInterface 
{ 
    private $currentUser; 

    public function __construct(TokenStorage $tokenStorage) 
    { 
     $this->currentUser = $tokenStorage->getToken()->getUser(); 
    } 

    public static function getSubscribedEvents() 
    { 
     return array(
      array(
       'event' => 'serializer.post_serialize', 
       'method' => 'onPostSerialize', 
       'class' => Exercise::class, // if no class, subscribe to every serialization 
       'format' => 'json', // optional format 
      ), 
     ); 
    } 

    public function onPostSerialize(ObjectEvent $event) 
    { 
     if (!$this->currentUser) { 
      return; 
     } 

     $exercise = $event->getObject(); 
     $visitor = $event->getVisitor(); 

     $results = $exercise->getUserResults($this->currentUser); 
     dump($results); // <-- It is an ArrayCollection with many elements 

     $visitor->setData(
      'my_user_results', 
      $results // <-- when rendered is an empty {} 
     ); 
    } 
} 

不幸的是,​​財產永遠是空的!
我看着成串行的源代碼,我發現:

/** 
* Allows you to add additional data to the current object/root element. 
* @deprecated use setData instead 
* @param string $key 
* @param integer|float|boolean|string|array|null $value This value must either be a regular scalar, or an array. 
*              It must not contain any objects anymore. 
*/ 
public function addData($key, $value) 
{ 
    if (isset($this->data[$key])) { 
     throw new InvalidArgumentException(sprintf('There is already data for "%s".', $key)); 
    } 

    $this->data[$key] = $value; 
} 

請注意不得包含任何對象了。

我該如何解決這個問題?

回答

1

請嘗試使用serializer.post_serialize事件而不是serializer.pre_serialize之一。此外,您的虛擬屬性名稱(user_results)應該與任何現有的可序列化字段不同。

setData方法的第二個參數必須是常規標量或數組。它不得包含任何對象。我建議將JMS串行器注入到監聽器類中,以將對象數組序列化爲標量數組。

<?php 

namespace AppBundle\Serializer; 

use JMS\Serializer\EventDispatcher\EventSubscriberInterface; 
use JMS\Serializer\EventDispatcher\PreSerializeEvent; 
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; 
use JMS\Serializer\EventDispatcher\ObjectEvent; 
use JMS\Serializer\Serializer; 

class ExerciseSubscriber implements EventSubscriberInterface 
{ 
    private $currentUser; 
    private $serializer; 

    public function __construct(TokenStorage $tokenStorage, Serializer $serializer) 
    { 
     $this->currentUser = $tokenStorage->getToken()->getUser(); 
     $this->serializer = $serializer; 
    } 

    public static function getSubscribedEvents() 
    { 
     return array(
      array(
       'event' => 'serializer.post_serialize', 
       'method' => 'onPostSerialize', 
       'class' => Exercise::class, // if no class, subscribe to every serialization 
       'format' => 'json', // optional format 
      ), 
     ); 
    } 

    public function onPostSerialize(ObjectEvent $event) 
    { 
     if (!$this->currentUser) { 
      return; 
     } 

     $exercise = $event->getObject(); 
     $visitor = $event->getVisitor(); 

     $visitor->setData(
      'user_results', 
      $this->serializer->toArray($exercise->getUserResults($this->currentUser)) 
     ); 
    } 
} 
+0

我用正確的事件'post_serialize'更新了我的答案,但它不起作用。請用粗體查看我最後的評論。 – StockBreak

+0

更新了我的答案。 $結果變量不應該包含任何對象。請在調用setData方法之前序列化它。 –

+0

問題是'getUserResults'返回'ExerciseResult'列表。如果我在調用'setData'之前序列化它,它不會顯示爲序列化字符串(編碼)? – StockBreak