Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
445 views
in Technique[技术] by (71.8m points)

symfony - Symfony2, FOSRestBundle. How to use group with JMSSerializerBundle?

I have entity:

<?php
namespace AppBundleEntity;

use DoctrineORMMapping as ORM;
use JMSSerializerAnnotationGroups;
//...


 /**
   * @ORMEntity(repositoryClass="AppBundleRepositoryUserRepository")
  **/
 class User extends BaseUser
 {
   /**
    * @ORMId
    * @ORMColumn(type="integer")
    * @ORMGeneratedValue(strategy="AUTO")
    * @Groups({"default"})
   */
protected $id;

/**
 * @ORMManyToMany(targetEntity="StorageBundleEntityFile")
 * @ORMJoinTable(name="users_photos",
 *      joinColumns={@ORMJoinColumn(name="user_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORMJoinColumn(name="photo_id", referencedColumnName="id", onDelete="CASCADE")}
 *      )
 * @Groups({"default"})
 */
protected $photoFiles;

/**
 * @ORMColumn(type="string", length=255, nullable=true, unique=false)
 * @Groups({"notification"})
 */
protected $deviceId;

 /**
 * @ORMColumn(type="string", length=255, nullable=true, unique=false)
  *     @Groups({"default"})
 */
protected $name;

/**
 * @ORMOneToOne(targetEntity="AppBundleEntityCar", mappedBy="driver")
 * @Groups({"driver"})
 */
private $car;

/**
 * @var DateTime $created
 *
 * @GedmoTimestampable(on="create")
 * @ORMColumn(type="datetime")
 * @Groups({"default"})
 */
protected $created;

/**
 * @var DateTime $updated
 *
 * @GedmoTimestampable(on="update")
 * @ORMColumn(type="datetime")
 * @Groups({"default"})
 */
protected $updated;


}

My Controller:

<?php
namespace AppBundleController;

use AppBundleEntityUser;
//...

class UsersController extends AppController{

    /**
     * Get list of Admins
     * @AnnotationsGet("/api/v1/admins", name="list_of_admins")
     * @return FOSRestBundleViewView
     */
    public function getAdminsAction(){

        if(!$this->isGranted('ROLE_ADMIN')){
            throw new AccessDeniedException('Only for Admin');
        }

        $admins = $this->getDoctrine()->getRepository('AppBundle:User')->findByRole('ROLE_ADMIN');

        return $this->view(['data' => $admins], Codes::HTTP_OK);

    }

}

A user with role ROLE_ADMIN does not have the car (car have only users with role ROLE_DRIVER). When I try to get all admins I get this:

{
  "id": 4,
  "username": "admin@site.com",
  "email": "admin@site.com",
  "roles": [
    "ROLE_ADMIN"
  ],
  "photoFiles": [],
  "name": "Andrii",
  "car": null
}

I tried add Groups. What I need to add my controller to receive data only from group default and notification

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As reminder, Groups in JMSSerializer are used as exclusion strategy.

An exclusion strategy consists to a specific approach used to expose/exclude properties depending on condition/context.

In order to use them correctly, the first thing you have to do is exclude all properties of your entity :

// ...
use JMSSerializerAnnotation as JMS;

/**
 * @ORMEntity(repositoryClass="AppBundleRepositoryUserRepository")
 * @JMSExclusionPolicy("all")
 */
class User extends BaseUser

Now, you have explicitly expose properties depending on Groups :

/**
 * @ORMColumn(type="string", length=255, nullable=true, unique=false)
 * @JMSGroups({"default"}) // Idem for all properties you want render in group "default"
 */
protected $name;

/**
 * @ORMColumn(type="string", length=255, nullable=true, unique=false)
 * @JMSGroups({"notification"})
 */
protected $deviceId;

Then, you have to define the used Group in your controller action :

/**
 * Get list of Admins
 * @AnnotationsGet("/api/v1/admins", name="list_of_admins")
 * @AnnotationsView(serializerGroups={"default", "notification"}) // Here set the Group used
 * @return FOSRestBundleViewView
 */
public function getAdminsAction()
{
    if(!$this->isGranted('ROLE_ADMIN')){
        throw new AccessDeniedException('Only for Admin');
    }

    $admins = $this->getDoctrine()->getRepository('AppBundle:User')->findByRole('ROLE_ADMIN');

    return $this->view(['data' => $admins], Codes::HTTP_OK);
}

Now, $admins contains only the properties exposed to the group default and notification.

You can also do it manually instead of use an annotation :

$view = $this->view($admins, 200);
$view->setSerializerGroups(array('default', 'notification'));

return $this->handleView($view);

For more informations, see Exclusion strategies .

I hope it's clear for you.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...