2012-11-07 26 views
6

我有一個用於用戶註冊的表單,並且只有用戶名字段存在於表單中。而在我的表格中,我希望允許用戶只輸入用戶名。 Nicename與註冊用戶名相同。驗證字段不在表單中,但在實體中

這種形式的綁定到用戶的實體,即,在我的形式類型的類:

public function setDefaultOptions(OptionsResolverInterface $resolver) 
{ 
    $resolver->setDefaults(array(
     'data_class' => 'Some\Bundle\Entity\User', 
    )); 
} 

實體用戶,其中有一個NotBlank約束兩者的用戶名和nicename設置。

namespace Some\Bundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Symfony\Component\Validator\Constraints as Constraints; 

//... 

class User 
{ 
    //... 

    /** 
    * @var string $username 
    * 
    * @ORM\Column(name="user_login", type="string", length=60, unique=true) 
    * @Constraints\NotBlank() 
    */ 
    private $username; 

    /** 
    * @var string $nicename 
    * 
    * @ORM\Column(name="user_nicename", type="string", length=64) 
    * @Constraints\NotBlank() 
    */ 
    private $nicename; 

    //... 

但是,如果我建立只有用戶名而不是nicename一種形式,對驗證即$form->isValid()它無法驗證。

要繞過這個問題,我想出了以下內容:

namespace Some\Bundle\Controller; 

use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Some\Bundle\Form\Type\RegisterType; 
//... 

class UserController extends Controller 
{ 
    //... 
public function registerAction() 
{ 
    //... 
    $request = $this->getRequest(); 
    $form = $this->createForm(new RegisterType()); 

    if ($request->getMethod() == 'POST') { 
     // force set nicename to username. 
     $registerFields = $request->request->get('register'); 
     $registerFields['nicename'] = $registerFields['username']; 
     $request->request->set('register', $registerFields); 

     $form->bind($request); 

     if ($form->isValid()) { 
      $user = $form->getData(); 
      //persist $user, etc... 

而在形式I型內容添加到我的buildForm方法:

$builder->add('nicename', 'hidden'); 

但我覺得這是非常不雅,留下一些對控制器的負擔(從請求對象中提取,放入數據,並將其放回請求對象,哎!),如果用戶要檢查生成的HTML的源代碼,用戶可以看到隱藏的字段。

反正是有至少能使用表單類型不需要做這樣的事情上面,同時保留了實體約束任何控制器?

我無法改變它備份用戶實體表模式,我想保持NotBlank約束。


編輯:長的麻煩後,我決定使用驗證組和它的工作。

class User 
{ 
//... 

/** 
* @var string $username 
* 
* @ORM\Column(name="user_login", type="string", length=60, unique=true) 
* @Constraints\NotBlank(groups={"register", "edit"}) 
*/ 
private $username; 

/** 
* @var string $nicename 
* 
* @ORM\Column(name="user_nicename", type="string", length=64) 
* @Constraints\NotBlank(groups={"edit"}) 
*/ 
private $nicename; 

表單類型:

public function setDefaultOptions(OptionsResolverInterface $resolver) 
{ 
    $resolver->setDefaults(array(
     'data_class' => 'Some\Bundle\Entity\User', 
     'validation_groups' => array('register', 'Default') 
    )); 
} 

'Default'需要或者忽略所有其他限制,我在buildForm形式式方法添加......你要知道,它的區分大小寫:'default'不起作用。

雖然,我覺得這是不夠的(和抱歉,我沒有把它放在我原來的問題),因爲當我堅持,我需要做這在我的控制器:

$user->setNicename($user->getUsername()); 

由於獎勵,我移動此從控制器通過添加Form Event Subscriber

在形式類型buildForm法形成類型級別:

$builder->addEventSubscriber(new RegisterPostBindListener($builder->getFormFactory())); 

而RegisterPostBindListen呃類

<?php 
namespace Some\Bundle\Form\EventListener; 

use Symfony\Component\Form\Event\DataEvent; 
use Symfony\Component\Form\FormFactoryInterface; 
use Symfony\Component\EventDispatcher\EventSubscriberInterface; 
use Symfony\Component\Form\FormEvents; 

class RegisterPostBindListener implements EventSubscriberInterface 
{ 

public function __construct(FormFactoryInterface $factory) 
{ 

} 

public static function getSubscribedEvents() 
{ 
    return array(FormEvents::POST_BIND => 'setNames'); 
} 

public function setNames(DataEvent $event) 
{ 
    $data = $event->getData(); 

    $data->setNicename($data->getUsername()); 
} 
} 

回答

0

在用戶的實體,您可以知道哪些領域可以可空:

/** 
*@ORM\Column(type="string", length=100, nullable=TRUE) 
*/ 
protected $someVar; 

這樣你的視圖控制器不需要做任何事情。

忘了提。您也可以定義初始化您nicename變量PrePersist條件:

// you need to first tell your User entity class it has LifeCycleCallBacks: 

/** 
* @ORM\Entity() 
* @ORM\HasLifecycleCallbacks() 
*/ 
class User 
{ 

    ... 

    /** 
    *@ORM\PrePersist 
    */ 
    public function cloneName() 
    { 
     $this->nicename = $this->username; 
    } 
} 
+0

我不能設置爲空,因爲該實體是基於我的模式無法更改的表。 ......當然我可以,但我會冒着SQL錯誤持續存在。 – luiges90

+0

在你實體的__construct()函數中,你能簡單地給實體一些默認值來防止NULL錯誤。 – Zhang

+0

我想保留實體的NotBlank約束。我試過用你的方式,但只有在該字段沒有'@Constraints \ NotBlank()'時才能工作。 – luiges90

0

在這種情況下,您應該使用一個Callback斷言來創建自定義驗證規則。