ユーザー登録用のフォームがありますが、フォームにはユーザー名フィールドのみが表示されます。そして私のフォームでは、ユーザーがユーザー名のみを入力できるようにしたいと思います。Nicenameは、登録時のユーザー名と同じになります。
このフォームは、ユーザーエンティティにバインドされています。つまり、私のフォームタイプクラスでは次のようになります。
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Some\Bundle\Entity\User',
));
}
エンティティUser。usernameとnicenameの両方にNotBlank制約が設定されています。
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...
そして、フォームタイプで、これをbuildForm
メソッドに追加します。
$builder->add('nicename', 'hidden');
しかし、これは非常にエレガントではなく、コントローラーにいくらかの負担を残し(リクエストオブジェクトから抽出し、データを入力して、リクエストオブジェクトに戻します、痛いです!)、ユーザーが非表示のフィールドを確認できるようになります。生成されたHTMLのソースコード。
とにかく、フォームタイプを使用する少なくともすべてのコントローラーが、エンティティの制約を保持しながら、上記のようなことを行う必要がないということはありますか?
Userエンティティをバックアップするテーブルスキーマを変更できません。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());
ボーナスとして、フォームイベントサブスクライバーを追加して、これをコントローラーからフォームタイプレベルに移動します
フォームタイプのbuildForm
方法:
$builder->addEventSubscriber(new RegisterPostBindListener($builder->getFormFactory()));
そしてRegisterPostBindListenerクラス
<?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());
}
}