Symfony のフォーム検証処理に問題があります。データに基づいてエンティティにバインドされたフォームを検証したいと思います。FormEventsを使用してフォームフィールドを動的に変更する方法については、非常に多くの情報があります。このトピックで欠けているのは、検証を制御/変更する方法です。
私の単純化されたユースケースは次のとおりです。
- ユーザーはカレンダーにイベントを追加できます。
- 検証では、イベントが既に存在するかどうかがチェックされます。
- 競合がある場合、検証でエラーがスローされます。
- ユーザーは、このエラー/警告を無視できるようになりました。
検証は、ターゲットとしてValidator
withConstraint::CLASS_CONSTRAINT
として実装されます (さらにいくつかの要素が考慮されているため)。
私がしようとしました:
- 検証グループをハックしましたが、エンティティ全体のバリデーターへのアクセスが見つかりませんでした。
- をハックして、
FormEvents
「日付の警告を無視する」などのフィールドを追加します。 - 送信ボタンをハックして、「強制送信」のようなものに変更します。
...しかし、実用的な解決策は見つかりませんでした。単一のプロパティー・ベースのバリデーターを使用したさらに単純なハックはうまくいきませんでした。:(
検証を動的に制御する Symfony の方法はありますか?
編集:私のコードは次のようになります:
use Doctrine\ORM\Mapping as ORM;
use Acme\Bundle\Validator\Constraints as AcmeAssert;
/**
* Appointment
*
* @ORM\Entity
* @AcmeAssert\DateIsValid
*/
class Appointment
{
/**
* @ORM\Column(name="title", type="string", length=255)
*
* @var string
*/
protected $title;
/**
* @ORM\Column(name="date", type="date")
*
* @var \DateTime
*/
protected $date;
}
サービスとして使用されるバリデータ:
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Validates the date of an appointment.
*/
class DateIsValidValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($appointment, Constraint $constraint)
{
if (null === $date = $appointment->getDate()) {
return;
}
/* Do some magic to validate date */
if (!$valid) {
$this->context->addViolationAt('date', $constraint->message);
}
}
}
エンティティ クラスを対象とするように、対応するConstraint
クラスが設定されます。
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
*/
class DateIsValid extends Constraint
{
public $message = 'The date is not valid!';
/**
* {@inheritdoc}
*/
public function getTargets()
{
return self::CLASS_CONSTRAINT;
}
/**
* {@inheritdoc}
*/
public function validatedBy()
{
return 'acme.validator.appointment.date';
}
}
編集2:試してみてくださいFormEvents
...私もすべての異なるイベントを試しました。
$form = $formFactory->createBuilder()
->add('title', 'text')
->add('date', 'date')
->addEventListener(FormEvents::WHICHONE?, function(FormEvent $event) {
$form = $event->getForm();
// WHAT TO DO HERE?
$form->getErrors(); // Is always empty as all events run before validation?
// I need something like
if (!$dateIsValid) {
$form->setValidationGroup('ignoreWarning');
}
});
編集 3: 制約が正しく宣言されています。それは問題ではありません:
services:
validator.acme.date:
class: AcmeBundle\Validator\Constraints\DateValidator
arguments: ["@acme.other_service"]
tags:
- { name: validator.constraint_validator, alias: acme.validator.appointment.date }