FOSRestBundle与BazingaHateoasBundle集成,但响应中仍然缺少链接

时间:2019-03-31 05:44:00

标签: php symfony

我正在尝试将FOSRestBundleBazingaHateoasBundle集成在一起,但是响应中仍然缺少链接(我希望会自动生成)。我的设置有什么问题?

这是我的配置:

composer.json [摘录]:

"require": {
    "php": "^7.1.3",
    "friendsofsymfony/rest-bundle": "^2.5",
    "jms/serializer-bundle": "^2.4",
    "lexik/jwt-authentication-bundle": "^2.6",
    "sensio/framework-extra-bundle": "^5.2",
    "stof/doctrine-extensions-bundle": "^1.3",
    "symfony/flex": "^1.1",
    "symfony/framework-bundle": "4.2.*",
    "willdurand/hateoas-bundle": "^1.4"
},

jms_serializer.yaml:

jms_serializer:
    visitors:
        xml:
            format_output: '%kernel.debug%'

fos_rest.yaml:

fos_rest:
    zone:
        - { path: ^/api/* }
    view:
        view_response_listener:  true
    format_listener:
        rules:
            - { path: ^/api, prefer_extension: true, fallback_format: json, priorities: [ json ] }
    routing_loader:
        default_format: json
    body_listener:
        array_normalizer: fos_rest.normalizer.camel_keys
    serializer:
        serialize_null: true
    body_converter:
        enabled: true
        validate: true

这是我的课程:

PersonsController.php:

/**
 * @Rest\Route("/persons")
 */
class PersonsController extends AbstractFOSRestController
{
    /**
     * @Rest\Get("")
     * @return View
     */
    public function getList()
    {
        $repository = $this->getDoctrine()->getRepository(Person::class);

        $view = $this->view(
            $repository->findAll()
        );
        $view->getContext()->setGroups(['default']);

        return $view;
    }

}

Person.php

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
 * @ORM\Entity(repositoryClass="App\Repository\PersonRepository")
 * @UniqueEntity("slug")
 * @Serializer\ExclusionPolicy("all")
 * @Hateoas\Relation("self", href = "expr('/api/persons/' ~ object.getSlug())")
 */
class Person
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     * @Serializer\Expose
     * @Serializer\Groups({"default"})
     */
    private $name;

    /**
     * @ORM\Column(type="string", length=255, unique=true)
     * @Gedmo\Slug(fields={"name"})
     * @Serializer\Expose
     * @Serializer\Groups({"default"})
     * @Serializer\XmlAttribute
     */
    private $slug;

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

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

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getSlug()
    {
        return $this->slug;
    }

    public function setSlug($slug)
    {
        $this->slug = $slug;
        return $this;
    }

}

测试:

获取http://localhost:8000/api/groups响应:

[
    {
        "name": "person1",
        "slug": "person1"
    },
    {
        "name": "person2",
        "slug": "person2"
    }
]

预期:

[
    {
        "name": "person1",
        "slug": "person1",
        "_links": {
            "self": { "href": "http://example.com/api/persons/person1" }
        }
    },
    {
        "name": "person2",
        "slug": "person2",
        "_links": {
            "self": { "href": "http://example.com/api/persons/person2" }
        }
    }
]

已研究:

https://github.com/willdurand/BazingaHateoasBundle/blob/master/Resources/doc/index.md#serializing-objects-未显示与FOS软件包的集成。它只是手动构造响应。

https://github.com/willdurand/Hateoas/issues/238-建议删除serializedGroups,但我需要使用组才能正确隐藏/公开要显示的字段

Symfony and Wildurand/Hateoas Bundle - no links on JSON reposnse-OP只是手动构造了响应对象,因此实际上并未使用FOSRestBundle的功能

https://symfony.com/doc/master/bundles/FOSRestBundle/1-setting_up_the_bundle.html#b-enable-a-serializer-因为JMSSerializerBundle是我安装的唯一序列化程序,所以我假设它是FOSRestBundle用来自动序列化数据的序列化程序。因此,与我找到的解决方案相反,我不应该手动序列化数据并构造响应。

1 个答案:

答案 0 :(得分:0)

我只需要在 Relation 批注中添加 exclusion 属性,并指定应在其中显示的组。

/**
 * @ORM\Entity(repositoryClass="App\Repository\PersonRepository")
 * @UniqueEntity("slug")
 * @Serializer\ExclusionPolicy("all")
 * @Hateoas\Relation(
 *   "self", 
 *   href = "expr('/api/persons/' ~ object.getSlug())",
 *   exclusion = @Hateoas\Exclusion(groups={"default"})
 * )
 */
class Person
{ ...