【发布时间】:2018-04-23 13:47:50
【问题描述】:
我正在使用 Symfony 4 和 FOSRestBundle 构建 API。我有非常基本的关系:
实体:User.php
/**
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
*/
class User
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
* @JMS\Groups({"onlyId"})
*/
private $id;
/**
* @ORM\Column(unique=true, type="string", length=255)
*/
private $email;
//...
/**
* @ORM\OneToMany(targetEntity="App\Entity\UserProduct", mappedBy="user", orphanRemoval=true)
*/
private $userProducts;
实体:UserProduct.php
/**
* @ORM\Entity(repositoryClass="App\Repository\UserProductRepository")
*/
class UserProduct
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
* @JMS\Groups({"onlyId"})
*/
private $id;
//...
/**
* @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="userProducts")
* @JMS\Groups({"onlyId"})
*/
private $user;
配置:fos_rest.yaml
fos_rest:
body_converter:
enabled: true
view:
view_response_listener: 'force'
formats:
json: true
routing_loader:
default_format: json
# param_fetcher_listener: true
# allowed_methods_listener: true
# routing_loader: true
# view:
# view_response_listener: true
# exception:
# codes:
# App\Exception\MyException: 403
# messages:
# App\Exception\MyException: Forbidden area.
format_listener:
rules:
- { path: ^/api, prefer_extension: true, fallback_format: json, priorities: [ json, html ] }
- { path: ^/login_check, stop: true }
- { path: ^/register, stop: true }
起初,当我发布用户 ID 和 JSON 数据时,我无法 POST UserProduct 将 JSON 发送到端点,因为它会抛出它期望 entity 的实例,而不是 @ 987654326@ 或我发送的任何内容。我在本教程中发现了这一点 -> https://medium.com/@maartendeboer/using-the-symfony-serializer-with-doctrine-relations-69ecb17e6ebd
它使用 Symfony 序列化器。当返回 FOSRestBundle 的 View 时,我得到的是 circular reference 错误。在这一点上,我知道 circular reference 错误可以使用 JMS Serializer 工具很好地处理,并在我的 postUserProductAction 控制器中使用它:
POST 一个产品并处理 circular reference 我使用这个控制器(使用教程中自定义编写的反序列化方法反序列化发布的 JSON,将其插入数据库,然后返回 Response (不是视图)在 JMS 序列化器及其组的帮助下):
class UserProductController extends FOSRestController
{
/**
* @Rest\Route("/api/product", name="userProduct")
*
*
* @Method("POST")
*
* @param Request $request
* @param SerializerInterface $serializer
* @return Response
* @throws \InvalidArgumentException
*/
public function postUserProductAction(Request $request, SerializerInterface $serializer): View
{
$userProduct = $serializer->deserialize($request->getContent(), UserProduct::class, 'json');
dump($userProduct);
$em = $this->getDoctrine()->getManager();
$em->persist($userProduct);
$em->flush();
$userProduct = $this->JMSSerializeWithGroups($userProduct,array('onlyId'));
return new View($userProduct, Response::HTTP_OK);
}
}
/**
* @param $entity
* @param array $groupArray
* @return mixed|string
*/
public function JMSSerializeWithGroups($entity, Array $groupArray)
{
$JMSserializer = SerializerBuilder::create()->build();
$entity = $JMSserializer->serialize( $entity, 'json', SerializationContext::create()->setGroups($groupArray));
return $entity;
}
我得到的回复很好,很清楚:
{
"id": 100,
"user": {
"id": 9
}
}
但这似乎有很多不必要的步骤。此外,如果我选择这种方法,我需要自己将 JMS 序列化添加到我的每个控制器(GET、PUT 等)中。
所以我的问题是为什么 FOSRestBundle 默认不使用 JMS 来呈现 View,正如其文档中所说的那样(如果已安装并注册)?我还应该在某处添加它以便 FOSRestBundle 识别它吗?如果可以的话,我一开始就不需要使用 Symfony 序列化器?我想我可能会迷失在所有 Symfony 4 升级中。
谢谢!
【问题讨论】:
标签: php symfony symfony4 fosrestbundle jms-serializer