0

I have 2 entities : User, Article and a many-to-many relationship with attribute to describe the User interactions with the Articles . The attribute describe the kind of interaction (like, bookmark...).

In this case, i need an intermediate entity (UserArticle) with a One-to-many relationship from Article towards UserArticle : the property is called userInteractions in the Article entity.

It's an API and when I create the Query Builder, I get this kind of result for an Article that has been liked and bookmarked by the current logged-in user:

//Article Json Object
{ 
       ...
       userInteractions : [
         {
            "type": "like"
         },
         {
            "type": "bookmark"
         }
       ]

}

That's OK but not convenient for the javascript frontend : I would prefer to expose boolean fields : isLiked : true, bookmarked: true, otheraction: false ... , because it is easier to parse.

I thought I had to write a custom hydrator. I did it for another relationship (many-to-many without attributes) and it works like a charm but in this case it works only when there is 0 or one interaction. If there are 2 or more actions, I get a 500 error and a notice when I call the parent Doctrine Object hydrator. Here's my hydrator :

class ArticleHydrator extends ObjectHydrator {
  protected function hydrateRowData(array $data, array &$result)
  {

    $hydratedResult = [];
    parent::hydrateRowData($data, $hydratedResult);
    //this call generates a notice Undefined offset: 0 at line 525 of    doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php

    $article->setUserInteractionsFlags(); 
    // works with less than 2 interactions in the left join and correctly hydrates the not-persisted booleans added to Article entity
 }

}

I tried to look in the Object hydrator but it's a real mess and not easily understandable and I thought that maybe, in this case using a custom hydrator is not appropriate. Any advise ? Thanks

plancton
  • 13
  • 3
  • If you only use this information with javascript frontend you shouldn't use a custom hydrator at all but I rather recommend to customize your serialization only - what kind of serialization do you use? – LBA Apr 16 '18 at 12:23
  • The serialization is made automatically by FosRestBundle in conjunction with JMS serializer by the magic of annotations. It takes the object returned by the Doctrine repository and returns a json view. You mean I should take back the control of the serialization context ? – plancton Apr 16 '18 at 19:37

1 Answers1

0

If you want expose the attribute with the JMS serializer just in order to make it easier for the consuming client to read (and especially are not expecting to write back this attribute, but OP does not give a hint to this direction):

Just use a virtual property:

 /**      @Serializer\VirtualProperty()      
@JMS\SerializedName("user_interaction_flags")    */

 public function getInteractionFlags() 
 {
     return array("like" => $this->...);
 }

You could even exclude the "original" attributes from being serialized if you don't require them.

LBA
  • 3,859
  • 2
  • 21
  • 60