Я унаследовал приложение, и я (пока) не являюсь экспертом по Symfony. Приложение имеет простую сущность пользователя (среди прочего, конечно) и имеет некоторые уникальные ограничения:
/**
* User
*
* @ORM\Table(name="users")
* @ORM\Entity
* @UniqueEntity(
* fields={"username", "school"},
* message="There's already a registered user with that login in this school."
* )
* @UniqueEntity(fields={"email"},
* message="That email is already registered")
* )
*/
При создании формы и при нарушении таких ограничений сообщения отображаются в самой форме, и поток не возвращается к контроллеру (что совершенно нормально).
У меня есть свойство, отличное от ORM, с $plainPassword, которое содержит введенный текст в форме вместе с обычным $password, сохраняющим зашифрованный пароль. Это часть формы для этого поля:
$builder->add(
'plainPassword',
TextType::class,
[
'required' => false,
'attr' =>
[
'autocomplete' => 'off',
],
'error_bubbling' => true,
]
)
;
Теперь для пароля у меня есть собственный валидатор, который можно увидеть в следующей функции:
public function isPasswordValid(string $p = null)
{
if (null==$p) {
$p = $this->getPlainPassword();
}
// If I'm not changing the password, there must be one previously
$success = strlen($this->getPassword())>0;
if (strlen($p)) {
$success = (strlen($p)>7 && preg_match('/[A-Za-z]/', $p) && preg_match('/[0-9]/', $p));
}
return $success;
}
Эта функция прекрасно работает сама по себе, но я хочу прикрепить ее к форме, чтобы, когда поле plainPassword имеет «неверный» пароль (т. е. функция возвращала false). Итак, я попытался использовать блок аннотаций прямо перед функцией:
/**
* @Assert\IsTrue(message = "The password is not a valid password")
*/
public function isPasswordValid(string $p = null)
{
if (null==$p) {
$p = $this->getPlainPassword();
}
// If I'm not changing the password, there must be one previously
$success = strlen($this->getPassword())>0;
if (strlen($p)) {
$success = (strlen($p)>7 && preg_match('/[A-Za-z]/', $p) && preg_match('/[0-9]/', $p));
}
return $success;
}
Сообщение отправляется в form.errors, и я мог бы показать его, когда форма вызывается в немодальном режиме очень специфическим (но другим) способом, но поведение формы по умолчанию через ajax, отображаемое как всплывающее окно, даже пропускает это поведение, поэтому я не получаю это сообщение. Затем я попытался с помощью error_mapping в определении поля в форме связать свойство и функцию, но результат тот же (т.е. он не показан).
Я даже пытался создать собственный валидатор. Во всех этих случаях поведение при проверке пароля нормальное, но когда пароль недействителен, форма не отправляется, но вообще не появляется сообщение об ошибке (в отличие от других полей, определенных в @UniqueConstraint). Итак, я либо отменяю, либо просто ввожу правильный пароль и отправляю форму, но у пользователя нет этой ссылки об ошибке (и профайлер или журналы разработчиков ничего не показывают об этом, поэтому я должен выяснить путем смены пароля).
Итак, должно быть что-то, что я упускаю, или просто с помощью средств, которые я тестировал, это невозможно. Сейчас я погружаюсь с языком выражений для утверждения выражения, но у меня заканчиваются идеи, и мне требуется пара дней только на это, поэтому я прошу вашей помощи на этом этапе, чтобы выяснить, что я сделал неправильно. , проглядели или еще не сделали.
Заранее спасибо.
ОБНОВЛЕНИЕ: добавлен пользовательский валидатор, где я не уверен, правильно ли я управляю пустыми данными или чем-то связанным.
// ValidPassword.php
namespace XXX\UsersBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
*/
class ValidPassword extends Constraint
{
public $message = 'InvalidPasswordMessage';
}
(Я хочу, чтобы сообщение обрабатывалось файлом перевода.)
// ValidPasswordValidator.php
namespace XXX\UsersBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use XXX\UsersBundle\Entity\User;
class ValidPasswordValidator extends ConstraintValidator
{
public function validate($p, Constraint $constraint)
{
$success = true;
if (strlen($p)) {
$success = (strlen($p)>7 && preg_match('/[A-Za-z]/', $p) && preg_match('/[0-9]/', $p));
}
if (!$success) {
$this->context->buildViolation($constraint->message)
->addViolation();
}
}
И в сущности:
use XXX\UsersBundle\Validator\Constraints as UserAssert;
...
/**
* @var string
* @UserAssert\ValidPassword
*/
private $plainPassword;
Это часть шаблона ветки для отображения задействованных полей:
...
<div class="row">
<div class="col-md-4">
{{ form_row(form.name) }}
</div>
<div class="col-md-4">
{{ form_row(form.surname) }}
</div>
</div>
<div class="row">
<div class="col-md-4">
{{ form_row(form.email) }}
</div>
</div>
<div class="row">
<div class="col-md-4">
{{ form_row(form.plainPassword) }}
</div>
</div>