2012-06-27 74 views
2

我剛剛創建了一個表單,它必須「捕捉」數據以將它們傳送到「用戶對象」並將其保存到數據庫中。
symfony2表單驗證和約束

爲了,爲做到這一點,我按照這些步驟:

  1. 創建一個用戶對象
  2. 創建UserRepository爲使其永久拿去(throught實體管理器)
  3. 創建類「地圖」的形式
  4. 創建路線和模板渲染整個事情

於是邁過前兩個那些,讓我們一起來看看第三步

<?php 
namespace Sestante\UserBundle\Form\Type; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilder; 
use Symfony\Component\Validator\Constraints\Email; 
use Symfony\Component\Validator\Constraints\MinLength; 
use Symfony\Component\Validator\Constraints\Collection; 

class AddUserType extends AbstractType 
{ 
    public function BuildForm(FormBuilder $builder, array $options) 
    { 
     $builder->add('username','text') 
       ->add('email','email') 
       ->add('id','hidden') 
       ->add('password','text') 
       ; 
    } 

    public function getName() 
    { 
     return 'AddUser'; 
    } 

這是我爲「形式處理」創建類的一部分。
很明顯,我想某種驗證添加到我的形式,並按照symfony2 book我做這個

public function getDefaultOptions(array $options) 
{ 
    $collectionConstraint = new Collection(array(
     'username'=> new MinLength(4), 
     'email'=>new Email(array('message'=>'invalid email address')), 
    )); 

    return array(
     'data_class' => 'Sestante\UserBundle\Entity\User', 
     'validation_constraint' => $collectionConstraint 
    ); 
} 

據我瞭解,約束將在$form->bindRequest(...)->bind(...)電話進行檢查。

所以,在我的控制,我已經做到了這一點

public function insertAction(Request $request) 
{ 
    if($request->getMethod() == 'POST'){ 
     $em = $this->getDoctrine()->getEntityManager(); 
     $user = $em->getRepository('SestanteUserBundle:User'); 
     $userObj = new User(); 
     $userObj->setSalt('prova'); 
     $parameters = $request->request->get('AddUser'); 
     $parameters['password'] = sha1($parameters['password']); 
     $userObj->setGroups($em->getRepository('SestanteUserBundle:Groups')->find(3)); 
     $form = $this->createForm(new AddUserType(), $userObj); 
     $logger = $this->get('logger'); 
     $logger->info('PROVA: '.gettype($parameters)); 
     $form->bind($parameters); /* al posto che fare un bind della form, faccio un bind normale con i parametri presi dalla post e modificati 
           vedi la password che deve subire uno sha1 */ 
     $em->persist($userObj); 
     $em->flush(); 
     return $this->redirect($this->generateUrl('SestanteUserBundle_homepage')); 
    } 

但正如我提交表單,我會和這個錯誤的鬥爭

預期類型數組的參數或遍歷和ArrayAccess,對象 給出

最奇怪的是,只有兩個對象涉及此操作(綁定參數和約束集合)是請求類型。 所以我不知道如何超過這個。
有什麼想法?

回答

3

嘗試這樣的事:

public function insertAction(Request $request) 
{ 
    // First: Create you're object with only what you need 
    $userObj = new User(); 

    // Then, build you're form 
    $form = $this->createForm(new AddUserType(), $userObj); 

    // Form submitted? 
    if ($request->getMethod() == 'POST') { 
     $request = $this->getRequest(); 
     $em = $this->getDoctrine()->getEntityManager(); 

     // Bind $request now ! 
     $form->bindRequest($request); 

     // Your object is updated (not saved, ofc). You can now do what you want. 
     $userObj->setPassword(sha1($user->getPassword()); 
     $userObj->setGroups($em->getRepository('SestanteUserBundle:Groups')->find(3)); 

     // Finish, save user 
     $em->persist($userObj); 
     $em->flush(); 

     return $this->redirect($this->generateUrl('SestanteUserBundle_homepage')); 
    } 
} 

一些其他的事情:

  • 你不需要把id字段在表單中。
  • 你應該看看sf2安全。在控制器中手動編碼 密碼並不是一個好主意。

編輯:

你得到了這個異常,因爲你不能用在處理對象的形式validation_constraint選項。

此選項只能用於數據數組。

+0

關於「手動編碼在控制器」我遵循該[頁](http://symfony.com/doc/current/book/security。html#book-security-encoding-user-password),它會說「將用戶密碼直接編碼到控制器中」。那麼,有什麼選擇,爲什麼寫這個食譜的symfony的開發者說的不同呢? 但是,我正在更改我的代碼來嘗試您的答案 – DonCallisto

+0

您的答案不是「好」,因爲它給了我同樣的錯誤。 – DonCallisto

+0

關於密碼編碼,您直接使用sha1方法。在食譜中,調用一個編碼器。 關於你的問題,你可以粘貼stacktrace的地方嗎? 如果您刪除了validation_constraint,表單工作是否正確? –