2017-01-09 5 views
0

たとえば、メイン(親)エンティティ(たとえばUser)と従属エンティティ(Post)の2つのエンティティがあります。 JMSシリアライザを使用してUserエンティティをシリアル化したいのですが、最初の投稿日の追加情報があります。 DBに格納された投稿日はtimestamp intですが、intを何らかのフォーマットで変換する私のヘルパー(ただのサービス)とシリアル化したいと思います。複合体シリアライゼーション

エンティティクラスでメソッドを使用してvirtual_propertyを作成しようとしましたが、エンティティクラスにヘルパーを挿入できませんでした。私のためにそれを解決する唯一の方法は、コントローラに自分でシリアライズすることです:

public function someAction() 
{ 
    $serializedUser = $this->serializeEntity($user); 
} 

public function serializeEntity(User $user) 
{ 
    // JMS serialization 
    $user = $this->get('jms_serializer')->serialize($user, 'array'); 

    if ($user->getPosts()->count()) { 
     $post = $user->getPosts()->first(); 
     $user['first_post_date'] = $this->get('my_helper_service')->dateFormat($post->getDate()); 
    } 

    return $user; 
} 

NB:この例では、私は、より複雑な方法だけでなく、日付フォーマッタを持っている現実の世界では、合成です。しかし、主なアイデアは同じです。

私はこれを行うより良い方法があると感じています。

答えて

3

Dmtryのソリューションは、あなたのケースでは完全に動作するはずです。

この場合、イベントリスナー/サブスクライバが最適なソリューションです。でもオブジェクトと連携し、JMSのシリアライザの全イベントシステムの一部を(Dmtryのソリューションは、プリミティブでのみ動作し、唯一のJSON/YAMLのためではなく、XML)をトリガします

もう少し一般的な解決策は、次のとおりです。

class MyFormatter implements EventSubscriberInterface 
{ 

    public static function getSubscribedEvents() 
    { 
     return array(
      array(
       'event' => 'serializer.post_serialize', 
       'method' => 'onPostSerialize', 
       'class' => 'YourEntity' 
      ), 
     ); 
    } 

    public function __construct(MyFormatter $foermatter) 
    { 
     $this->formatter = $formatter; 
    } 

    public function onPostSerialize(ObjectEvent $event) 
    { 
     $visitor = $event->getVisitor(); 
     $context = $event->getContext(); 

     $timestamp = $event->getObject()->getTimestamp(); 
     $formattedTime = $this->formatter->format($timestamp); 

     $metadata = new StaticPropertyMetadata('stdClass', 'first_post_date', $formattedTime); 

     $visitor->visitProperty($metadata, $formattedTime, $context); 
    } 
} 

stdClassは、シリアライザによって無視されています...

1

もちろん、より良い方法があります。シリアライゼーションイベントと呼ばれています。あなたはちょうどあなたがあなたのリスナー

public function myOnPostSerializeMethod(ObjectEvent $event) 
{ 
    if (!($event->getObject() instance of YourEntity)) { 
     return; 
    } 

    $timestamp = $event->getObject()->getTimestamp(); 

    $visitor = $event->getVisitor(); 
    $visitor->addData('date', $this->formatter->format($timestamp)); 
} 

P.S.に必要なデータを追加し

my_bundle.serializer_subscriber: 
    class: MyBundle\Serializer\MyEntitySerializerSubscriber 
    arguments: 
     - @bundle.time_formatter 
    tags: 
     - { name: jms_serializer.event_subscriber } 

とをイベントサブスクライバを作成

http://jmsyst.com/libs/serializer/master/event_system

私はコードをチェックしなかったので、メソッドの名前で間違っているかもしれませんが、そのアイデアは明確です。

+0

は、私がイベントを考えますが、このイベントの火災は、すべてシリアライズ上だろうか?私が移入したいいくつかのエンティティがある場合、コードにはSomeEntityの多くの 'if($ event-> getObject()インスタンスがあります){$ this-> someEntityFormat($ event);} } ' – Aliance