web-dev-qa-db-ja.com

マッピングされたfalseフォームフィールドを持つsymfony検証フォーム

オプションmappedfalseを追加したフィールドが追加されたフォームがあります。しかし、フォームを検証しようとすると、これらの特定のフォームフィールドの上に「この値は無効です」ということを示すパスはありません。このオプションは検証をバイパスするものではありませんか?

これらのフォームフィールドは、他のフィールドにデータを入力する場合にのみ有用であり、保存する必要もチェックする必要もありません。

私が見つけた唯一の解決策は、送信ボタンをクリックするとjsですべての余分なフィールドを削除することです。

32
kzrdt

この投稿はSymfony 2.3の最新情報ではありません

以下のコメントを読む

新しいバージョンが登場します!

フォーム内のマッピングされていないフィールドの検証(Symfony 2.1.2)

これは、フォーム内の無制限またはマップされていないフィールドを検証する現在の方法に関するいくつかのstackoverflow質問に対するグローバルな回答です。

豊富なSymfony 2エコシステムにより、選択のフレームワークは急速に進化するツールになります。
symfony 2.1バージョンでは、多くの廃止予定があります。これは、Symfony 2.0から2.1.2で動作しているものがSymfony 2.3で動作しなくなることを意味します。この詳細については、 Symfony 2.0から2.1へのアップグレード を読み、Symfonyコードの@deprecatedコメントを読んでください。

非バインドフィールド

フォームを作成するときは、通常エンティティを使用し、エンティティ自体で検証アノテーションのタンクに検証を行うことができます。

namespace Dj\TestBundle\Entity;

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

/**    
 * Dj\TestBundle\Entity\Post
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Dj\TestBundle\Entity\PostRepository")
 */
class Post
{
    // ... some code

    /**
    * @var string $title
    * @ORM\Column(name="title", type="string", length=200, nullable=false)
    * @Assert\NotBlank()
    */
    private $title;

    // .. getters and setters
}

ただし、モデルにマップされていないフィールドをフォームに挿入する必要がある場合があります。

モデルの例は次のとおりです。

namespace Dj\TestBundle\Entity;

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

/**
 * Dj\TestBundle\Entity\Post
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Dj\TestBundle\Entity\PostRepository")
 */
class Post
{
    /**
     * @var integer $id
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**ghjkl
     * @var string $title
     * @ORM\Column(name="title", type="string", length=200, nullable=false)
     * @Assert\NotBlank()
     */
    private $title;

    // ... getters and setters
}

myExtraFieldという名前の追加フィールドをフォームに追加する場合は、次のようにします。

class PostType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('title')
                ->add('myExtraField', 'choice', array(
                        'label' => 'myExtraField option :',
                        'choices' => array(
                            1 => 'Option One',
                            2 => 'Option Wat !'
                        ),
                        'expanded' => true,
                        'mapped' => false
                   ));
    }
    // other methods
}

注意 :

  • mappedは、Symfony 2.3で廃止予定のproperty_pathを置き換えます
  • オプション配列に 'data' => 1エントリを追加することで、デフォルトの選択値をmyExtraFieldに追加できます。

サンプルコード:

$builder->add('title')
    ->add('myExtraField', 'choice', array(
        'label' => 'myExtraField option :',
        'choices' => array(
            1 => 'Option One',
            2 => 'Option Wat !'
        ),
        'data' => 1, // default selected option
        'expanded' => true,
        'mapped' => false
));

myExtraFieldフィールドを検証したい場合、Post Entity注釈では実行できません。フォームで実行する必要があります。

検証されたマッピングされていないフィールド-Symfony 2.0の方法

2.0の方法は、フォームビルダーにバリデーターを追加することでした($ builder-> addValidator(..))が、このメソッドは非推奨です!

namespace Dj\TestBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

// needed namespaces for 2.0 validation
use Symfony\Component\Form\CallbackValidator;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormError;

class PostType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // ... $builder->add()

        // VALIDATING NON MAPPED FIELD Symfony 2.0 way
        /** @var Symfony\Component\Form\CallbackValidator $myExtraFieldValidator **/
        $myExtraFieldValidator = new CallbackValidator(function(FormInterface $form){
          $myExtraField = $form->get('myExtraField')->getData();
            if (empty($myExtraField)) {
              $form['myExtraField']->addError(new FormError("myExtraField must not be empty"));
            }
        });
        // adding the validator to the FormBuilderInterface
        $builder->addValidator($myExtraFieldValidator);
    }
    // ... other methods
}

これは現在、myExtraFieldフィールドを検証していますが、But$ builder-> addValidatorはSymfony 2.3で終了します!

前方互換性のあるコード

Symfony 2.0から2.1へのアップグレード で述べたように、FormValidatorInterfaceが非推奨になったため、検証クロージャー関数をバインドされたイベントリスナーに渡す必要がありますFormEvents :: POST_BINDイベント。

これがコードです。

namespace Dj\TestBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

// needed namespaces for 2.1 validation
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormError;

class PostType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // ... $builder->add()

        // VALIDATING NON MAPPED FIELD Symfony 2.1.2 way (and forward)
        /** @var \closure $myExtraFieldValidator **/
        $myExtraFieldValidator = function(FormEvent $event){
            $form = $event->getForm();
            $myExtraField = $form->get('myExtraField')->getData();
            if (empty($myExtraField)) {
              $form['myExtraField']->addError(new FormError("myExtraField must not be empty"));
            }
        };

        // adding the validator to the FormBuilderInterface
        $builder->addEventListener(FormEvents::POST_BIND, $myExtraFieldValidator);
    }
    // ... other methods
}

これは確かにSfの達人の助けを借りて改善できますが、現時点では、前方互換性のある方法で非バインドフォームフィールドを検証します。

それが私たちの一部を解き放つ助けになることを願っています.

デビッド

74
David Jacquel

同様のトピックに関する質問で言及したようにSymfony 2.1以降では、 'constraints'オプションを使用して、マッピングされていないフィールドに検証を追加する必要があります:

use Symfony\Component\Validator\Constraints\MinLength;
use Symfony\Component\Validator\Constraints\NotBlank;

$builder
    ->add('firstName', 'text', array(
        'constraints' => new MinLength(3),
    ))
    ->add('lastName', 'text', array(
        'constraints' => array(
            new NotBlank(),
            new MinLength(3),
        ),
    ))
;

これで時間を失った私のような人を助けることを願っています...

30
Żabojad

already制約を使用している場合、これを行うことができます:

$builder
    ->add('new', 'repeated', array(
            'type' => 'password',
            'required'          => true,                    
            'invalid_message' => 'crmpicco.status.password_mismatch',
            'constraints'       => array(
                new NotBlank(),
                new Assert\Length([
                    'min'        => 2,
                    'max'        => 50,
                    'minMessage' => 'Your first name must be at least 2  characters long',
                    'maxMessage' => 'Your first name cannot be longer than 2 characters',
                ])
            )
        ))
    ->add('save', 'submit', array(
            'label' => 'password.form.fields.save',
        ))
    ;
5
crmpicco

マッピングされていないフィールドに基づくSymfony 3.4の式制約:

$resolver->setDefaults([
        'data_class' => MyClass::class,
        'constraints' => [
            new Expression([
                'expression' => 'this["endTime"].getData() >= this["startTime"].getData()',
                'message' => 'L\'heure de fin doit être plus grande ou égale à l\'heure de début'
            ])
        ]
    ]);
0

うまくいきました。 symfony 2.1を確認しました。コードは次のようになります。

$builder->add('password', 'password', ['required' => false, 'mapped' => false]);

もちろん、プロパティ「必須」は不要です。 ドキュメントの例