Symfony 3 FOS Rest + JMS Serializer组

时间:2016-12-14 01:37:43

标签: php symfony fosrestbundle jmsserializerbundle

我的composer.json(部分内容):

{
    "require": {
        "symfony/symfony": "3.1.*",
        "jms/serializer-bundle": "^1.1",
        "friendsofsymfony/rest-bundle": "^2.1"
    }
}

我有一些实体,我希望返回列表操作的部分数据,并完成查找操作。为此,我有这些文件:

Product.php

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;

/**
* @ORM\Entity
* @ORM\Table(name="represented")
* @JMS\ExclusionPolicy("ALL")
*/
class Product
{
    /**
    * @var integer
    * @ORM\Column(type="integer", nullable=false, options={"unsigned"=true})
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="AUTO")
    */
    protected $id;

    /**
    * @var string
    * @ORM\Column(type="string", nullable=false, length=48)
    */
    protected $name;

    /**
    * @var Group
    * @ORM\ManyToOne(targetEntity="Group", inversedBy="products")
    * @ORM\JoinColumn(name="group_id", referencedColumnName="id")
    */
    protected $group;

    public function getId()
    {
        return $this->id;
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setGroup(Group $group)
    {
        $this->group = $group;
    }

    public function getGroup()
    {
        return $this->group;
    }
}

ProductController.php

<?php

namespace AppBundle\Controller;

use FOS\RestBundle\Controller\Annotations\Get;
use FOS\RestBundle\Controller\FOSRestController;
use AppBundle\Entity\Product;

class ProductController extends FOSRestController
{
    /**
    * @Get("/product", name="list_products")
    */
    public function listAction()
    {
        $products = $this->getDoctrine()
            ->getRepository('AppBundle:Product')
            ->findBy([], [ 'name' => 'ASC' ]);

        $view = $this->view($products);

        return $this->handleView($view);
    }

    /**
    * @Get("/product/{id}", requirements={"id" = "\d+"}, name="get_product")
    */
    public function getAction($id)
    {
        $em = $this->getDoctrine()->getManager();

        $product = $em->getRepository('AppBundle:Product')
            ->find($id);

        if ( ! $product) {
            $error = [
                'error' => 'Product not found'
            ];

            $view = $this->view($error, 404);
        } else {
            $view = $this->view($product);
        }

        return $this->handleView($view);
    }
}

我希望能够在列表结果中不显示group属性。为此,我尝试了一些方法,主要是小组。

  1. 只需使用配置我要显示的属性的组名称即可 在我的Groups({"List"})列表中,并在此列表中引用该组 控制器@View(serializerGroups={"List"})。但这没有 影响所有属性都可见。
  2. 为整个实体配置@ExclusionPolicy("all")没有 也工作。
  3. 除ExclusionPolicy外,@Expose还有我想要的所有属性 在某些或所有组中显示,但这使得所有属性都被标记 显示。
  4. 我还尝试了其他一些变种,但没有任何改变结果。

2 个答案:

答案 0 :(得分:1)

控制器操作的结束不应该只是:

return $this->handleView($view);

但是要让一个或多个小组工作,你需要激活它们。在类的顶部,您需要添加FOSRest Context,而不是JMS上下文:

use FOS\RestBundle\Context\Context;

并在返回视图之前的控制器操作中:

$view = $this->view($products, 200);
$context = new Context();
$context->setGroups(['list']);
$view->setContext($context);

return $this->handleView($view);

这适用于Symfony 3.2和FOSRest 2.1和2.0。

升级FOSRest文档的链接: https://github.com/FriendsOfSymfony/FOSRestBundle/blob/master/UPGRADING-2.0.md

答案 1 :(得分:1)

如果您使用@Exclude,那么这应该有效。我使用的另一个选项是对config.yml进行少量添加:

fos_rest:
    serializer:
        groups: ['Default']

这要求实体属性位于组Default中以便序列化。如果您在属性上没有@Groups注释,那么它将位于Default中,但只要您添加@Groups注释,它就会不再位于Default组(除非您专门添加它。)

这允许默认序列化过程包括除@Groups注释之外的所有实体字段,然后在其他地方我可以序列化Default和我选择的其他组如果我想要一切包括在内。

// Function in the Controller class
public function getAction(MyEntity $me) {
    // Use automatic serializer, only things in 'Default' group are included
    return $me;
}