7

ユーザー登録用のフォームがありますが、フォームにはユーザー名フィールドのみが表示されます。そして私のフォームでは、ユーザーがユーザー名のみを入力できるようにしたいと思います。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());
}
}
4

3 に答える 3

2

検証グループを使用する必要があると思います。

于 2012-11-07T07:10:06.217 に答える
0

Userエンティティでは、どのフィールドをnull許容できるかを判断できます。

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

このように、ViewControllerは何もする必要がありません。

言及するのを忘れた。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;
     }
}
于 2012-11-07T04:45:56.200 に答える
0

この場合、コールバックアサーションを使用してカスタム検証ルールを作成する必要があります。

于 2012-11-07T11:38:55.210 に答える