2015-11-05 51 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