2015-11-05 46 views
2

我正在使用带有Restangular库的AngularJS来处理用Symfony2 + JMS Serializer + FOS Rest Bundle编写的Rest Api。通过AngularJS发送到Symfony2的对象/表单的验证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修改前端上的用户,例如从选择框中的可用选项中选择作业。的$scope.user JSON表示将看起来像这样:

{ 
    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类中创建了ViewTransformer。这将基本上将收到的作业对象转换为具有ID值的标量整数。 symfony.com/doc/current/cookbook/form/data_transformers.html

$builder->get('job')->addViewTransformer 

不过,我觉得这是不正确的做法和现在我想不出还有什么更好的主意的。将更复杂的对象发送到Symfony2 RESTful后端的最佳做法是什么?这只是一个简单的例子,但在我的应用job User类中的字段也可以包含Job实体的集合。

+0

我们基本上做的是,反序列化使用JMS(使用Doctrine对象的构造函数,而不是JMS的)东西,将它并入doctrinemanager和冲洗..听起来太简单了,它是那么容易!和您也可以简单地使用验证器服务,在刷新之前实际验证您的实体 –

回答

2

试试这个solution在您UserFormType

$jobTransformer = new EntityToIdObjectTransformer($this->om, "AcmeDemoBundle:Job"); 
$builder 
    ->add('firstName', 'text') 
    ... 
    ->add($builder->create('job', 'text')->addModelTransformer($jobTransformer)) 
+1

哇,我的情况一直在Symfony2文档中。感谢您指出了这一点。这是首选解决方案,因为@ Sam的解决方案不会放弃标准FormType。 – rsobon

3

东西沿着这些路线是我们使用:

$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从理论获取的实体,并将值应用于现有值,而不是创建新值,并将值应用于新值(可能以空字段结尾)

+0

如果我理解正确,您完全放弃了标准Symfony2 Form对象?您不要在Controller中使用$ form-> submit()或$ form-> handleRequest()?在$ form-> isValid()中验证呢? – rsobon

+0

事实上,我完全放弃了这个表单,而不是$ form-> isValid()来检查数据是否有效,我们使用验证器服务来验证对象(这就是表单在他的场景之后也会做的事情) –

+0

另一个问题。如果用户提交额外的数据会发生什么 - 编辑表单上未提供这些数据? validationGroups是否处理这个问题?例如,有“姓名”和“姓氏”的编辑表单,但用户也设法在请求中发送“性别”。如何防止此字段持续存在(FormType构建器具有这种机制)? – rsobon