2014-07-18 111 views
0

我正在Symfony 2中建立一個Web應用程序,其中我有一個用戶實體類來保存註冊用戶。Symfony2 - 使用實體值作爲默認當表單提交空字段

每個用戶至少應該有一個用戶名和一個密碼,因此,我使用@Assert\NotBlank驗證規則爲實體中的兩個字段。用戶名是靜態的,但是,能夠更改密碼是可取的。

因此,我正在構建一個表單,用戶可以在其中登錄更改其密碼(等等)。此表單利用Symfony中的重複字段類型進行密碼確認。

現在,在大多數情況下,我猜用戶不想更改密碼,而是更新其個人資料中的其他字段。因此,我希望它可以讓他們將密碼字段留空。但是,這會干擾NotBlank驗證規則。

刪除NotBlank驗證規則當然是一個選項。雖然,但我很難找到解決方案,因爲這會導致用戶以空白密碼結束的問題。

最後,據我所知,symfony Request對象在表單提交時自動將表單數據填充回User實體。

現在,我的問題是:有沒有什麼辦法,在空的密碼字段,使Symfony用數據庫中的現有密碼填充用戶實體而不是空白值?這將允許驗證通過,並且在保存時不會導致密碼的任何不希望的改變。

這是在該實體的密碼字段中的代碼

/** 
* @var string 
* 
* @ORM\Column(name="password",type="string",length=255) 
* @Assert\NotBlank() 
* @Assert\Type(type="string") 
* @Assert\Length(max="255") 
* @Assert\NotEqualTo(value="password") 
*/ 
private $password; 

這是用於產生形式

private function initForm($user) { 
    return $this->createFormBuilder($user) 
      ->add('name', 'text') 
      ->add('mail', 'email') 
      ->add('password', 'repeated', [ 
       'type' => 'password', 
       'invalid_message' => 'The password fields must match.', 
       'first_options' => ['label' => false], 
       'second_options' => ['label' => false] //set to false to hide label in view 
      ]) 
      ->add('save', 'submit')->getForm(); 
} 

這是/profile/edit頁面操作碼的代碼:

/** 
* @ParamConverter("user",class="MyBundle:User") 
*/ 
public function editAction(User $user, Request $request) { 

    $form = $this->initForm($user); 
    $form->handleRequest($request); 

    if ($form->isValid()) { 
     //update to database and redirect user back to profile_view 
     $this->getDoctrine()->getManager()->flush(); 
     return $this->redirect($this->generateUrl('profile_view')); 
    } 

    return $this->render('MyBundle:User:edit.html.twig', 
         array('form' => $form->createView())); 
} 

在此先感謝您的幫助!

編輯

我也嘗試了「明顯」的做法,即temporarilly存儲在一個變量的原始密碼和「放」回來,如果提交表單後,這是空白:

/** 
* @ParamConverter("user", 
        class="MyBundle:User") 
*/ 
public function editAction(User $user, Request $request) { 
    $password = $user->getPassword(); 

    $form = $this->initForm($user)->getForm(); 
    $form->handleRequest($request); 

    if ($user->getPassword() == NULL) { 
     $user->setPassword($password); 
     $form = $this->initForm($user)->getForm(); //this is the problem 

    } 

    if ($form->isValid()) { 
     //update to database and redirect user back to profile view 
     $this->getDoctrine()->getManager()->flush(); 
     return $this->redirect($this->generateUrl('profile_view')); 
    } 
    return $this->render('MyBundle:User:edit.html.twig', 
         array('form' => $form->createView())); 
} 

然而,這並不是因爲明顯的原因。當表單在if聲明中重新初始化時,Symfony發現表單從未首先提交,即不執行驗證。並且添加$form->handleRequest($request)讓我們回到密碼字段可能爲空的第一個問題。

雖然我發現有特殊之處。 Symfony驗證實體而不是表單。但刪除問題行$form->initForm($user)->getForm()仍然無效,但實體應該有效。

回答

1

我認爲這不是一個好主意。正確的方法是創建一個單獨的表單來更改用戶密碼。例如:twitterfacebookgoogle

+0

經過一番持續的研究,我相信你是對的!我會接受它作爲一個答案..但如果有人應該找到一種方式,我都是耳朵! – walander

+1

我完全忘了;非常感謝您的幫助! =) – walander

0

一種解決方法是使用一個額外的類成員$rawPassword,而不是存儲在數據庫中,你的表上僅使用。當然,您會保留您的問題中定義的數據庫存儲的變量$password

在您的編輯操作中,您只需在$form->bind($request);之後進行測試,如果您的用戶爲$rawPassword的密碼定義。如果是這種情況,請使用編碼值$rawPassword更新$password,然後刷新。

編輯:$form->bind($request);低於2.3,$form->handleRequest($request);否則。

+0

有趣的思想!這絕對適合我。非常感謝你!我也相信''form-> bind($ request)'方法從Symfony 2.3開始就被取消了。 – walander

+0

冬青牛!確實 !這是我的工作,謝謝你,我完全錯過了這一點。 –

1

我認爲這個解決方案在它自己的形式上存在一個EVENT。創建一個新用戶

  • 會放回到請求數據模型數據的現有用戶 與密碼字段爲空

  • 將觸發驗證時

    1. 將讓您的驗證完好對於模型數據(DB)中的密碼字段爲空的現有用戶

    ->addEventListener(FormEvents::PRE_SUBMIT,function(FormEvent $event) { 
    
        /** @var array $requestData */ 
        $requestData = $event->getData(); 
    
        /** @var \AppBundle\Entity\User $user */ 
        $user = $event->getForm()->getData(); 
    
        if ($user && !$requestData['password']){ 
         $requestData['password'] = $user->getPassword(); 
        } 
    
        $event->setData($requestData); 
    }) 
    

    FormEvents::PRE_SUBMIT將爲您提供2種數據類型的訪問權限,我在代碼中對它們各自的類型進行了評論。

    $requestData是來自用戶輸入的歸一化數據,這個數據將在這種情況下適用於模型$user,這將發生在事件PRE_SUBMIT之後。

    驗證將發生在$ requestData上,但僅在PRE_SUBMIT之後發生。

  • 相關問題