objects/forms 的验证通过 AngularJS 发送到 Symfony2 REST API
Validation of objects/forms sent via AngularJS to Symfony2 REST API
我正在使用 AngularJS 和 Restangular 库来处理用 Symfony2 + JMS Serializer + FOS Rest Bundle 编写的 Rest Api。
为了首先对用户实体执行 CRUD 操作,我让特定的用户显示:
var User = Restangular.one('users', $routeParams.userId);
User.get()
.then(function(response) {
$scope.user = response;
});
我收到 JSON 这样的回复:
{
id: 1,
firstName: "Howell",
lastName: "Weissnat",
job: {
id: 1
name: "Job Name"
}
}
然后我想修改用户实体中的job
字段。作业基本上是 Symfony 2 后端中独立的实体(更像是值对象),与用户实体具有 ORM 关系。
然后我通过 AngularJS 在前端修改用户,例如从选择框中的可用选项中选择作业。 JSON $scope.user
的表示形式如下所示:
{
id: 1,
firstName: "Howell",
lastName: "Weissnat",
job: {
id: 2
name: "Job Second Name"
}
}
然后我用 Restangular 发出 PUT 请求:
$scope.user.save();
不幸的是,Symfony2 期望接收这样的对象:
{
id: 1,
firstName: "Howell",
lastName: "Weissnat",
job: 2
}
其中 job: 2
基本上指向作业实体的 ID。
我成功地解决了在后端 UserType
class 中创建 ViewTransformer 的问题。这基本上会将接收到的作业对象转换为具有 ID 值的标量整数。
symfony.com/doc/current/cookbook/form/data_transformers.html
$builder->get('job')->addViewTransformer
但是我觉得这不是正确的方法,我现在想不出更好的主意。将更复杂的对象发送到 Symfony2 RESTful 后端的最佳做法是什么?这只是一个简单的示例,但在我的应用程序中,用户 class 中的 job
字段也可以包含 Job
实体的集合。
我们使用的是类似这样的东西:
$entity = $this->get('jms_serializer')->deserialize($request->getContent(), $entityName, 'json');
if (!$entity) {
throw new ApiException(Codes::HTTP_NOT_FOUND, null, 'entity with that id not found');
}
$violations = $this->get('validator')->validate($entity, $validationGroups);
if (count($violations) > 0) {
return $violations;
}
$this->getDoctrine()->getManager()->merge($entity);
$this->getDoctrine()->getManager()->flush();
并为您服务:
services:
jms_serializer.doctrine_object_constructor:
class: %jms_serializer.doctrine_object_constructor.class%
public: false
arguments: ["@doctrine", "@jms_serializer.unserialize_object_constructor"]
jms_serializer.object_constructor:
alias: jms_serializer.doctrine_object_constructor
基本上做的是确保 jms 从学说中获取实体,并将值应用于现有实体,而不是创建新实体并将值应用于新实体(并且可能结束一些空字段)
在您的 UserFormType
中尝试这个 solution
$jobTransformer = new EntityToIdObjectTransformer($this->om, "AcmeDemoBundle:Job");
$builder
->add('firstName', 'text')
...
->add($builder->create('job', 'text')->addModelTransformer($jobTransformer))
我正在使用 AngularJS 和 Restangular 库来处理用 Symfony2 + JMS Serializer + FOS Rest Bundle 编写的 Rest Api。
为了首先对用户实体执行 CRUD 操作,我让特定的用户显示:
var User = Restangular.one('users', $routeParams.userId);
User.get()
.then(function(response) {
$scope.user = response;
});
我收到 JSON 这样的回复:
{
id: 1,
firstName: "Howell",
lastName: "Weissnat",
job: {
id: 1
name: "Job Name"
}
}
然后我想修改用户实体中的job
字段。作业基本上是 Symfony 2 后端中独立的实体(更像是值对象),与用户实体具有 ORM 关系。
然后我通过 AngularJS 在前端修改用户,例如从选择框中的可用选项中选择作业。 JSON $scope.user
的表示形式如下所示:
{
id: 1,
firstName: "Howell",
lastName: "Weissnat",
job: {
id: 2
name: "Job Second Name"
}
}
然后我用 Restangular 发出 PUT 请求:
$scope.user.save();
不幸的是,Symfony2 期望接收这样的对象:
{
id: 1,
firstName: "Howell",
lastName: "Weissnat",
job: 2
}
其中 job: 2
基本上指向作业实体的 ID。
我成功地解决了在后端 UserType
class 中创建 ViewTransformer 的问题。这基本上会将接收到的作业对象转换为具有 ID 值的标量整数。
symfony.com/doc/current/cookbook/form/data_transformers.html
$builder->get('job')->addViewTransformer
但是我觉得这不是正确的方法,我现在想不出更好的主意。将更复杂的对象发送到 Symfony2 RESTful 后端的最佳做法是什么?这只是一个简单的示例,但在我的应用程序中,用户 class 中的 job
字段也可以包含 Job
实体的集合。
我们使用的是类似这样的东西:
$entity = $this->get('jms_serializer')->deserialize($request->getContent(), $entityName, 'json');
if (!$entity) {
throw new ApiException(Codes::HTTP_NOT_FOUND, null, 'entity with that id not found');
}
$violations = $this->get('validator')->validate($entity, $validationGroups);
if (count($violations) > 0) {
return $violations;
}
$this->getDoctrine()->getManager()->merge($entity);
$this->getDoctrine()->getManager()->flush();
并为您服务:
services:
jms_serializer.doctrine_object_constructor:
class: %jms_serializer.doctrine_object_constructor.class%
public: false
arguments: ["@doctrine", "@jms_serializer.unserialize_object_constructor"]
jms_serializer.object_constructor:
alias: jms_serializer.doctrine_object_constructor
基本上做的是确保 jms 从学说中获取实体,并将值应用于现有实体,而不是创建新实体并将值应用于新实体(并且可能结束一些空字段)
在您的 UserFormType
中尝试这个 solution$jobTransformer = new EntityToIdObjectTransformer($this->om, "AcmeDemoBundle:Job");
$builder
->add('firstName', 'text')
...
->add($builder->create('job', 'text')->addModelTransformer($jobTransformer))