Nano Hash - криптовалюты, майнинг, программирование

сообщение об ошибке symfony в форме при использовании пользовательского метода проверки

Я унаследовал приложение, и я (пока) не являюсь экспертом по 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>

  • Я подозреваю, что в вашем коде много проблем. Во-первых, часть // If I'm not changing the password, there must be one previously кажется ошибочной. PlainPassword будет пустым в вашем Entity почти все время, потому что этот атрибут используется для проверки и используется только в нескольких ситуациях. Взгляните на свой атрибут Entity и сначала проверьте. Во-вторых, куда вы поместите isPasswordValid? Я надеюсь, что не в вашей сущности, потому что сущности - это простые пакеты для данных (обычно поступают из БД). Не добавляйте проверку к сущностям. Используйте FormTypes и Validators на слоях контроллера. 14.08.2018
  • Свойство plainPassword сопоставляется с полем формы, поэтому все, что вводится, должно быть проверено. $p=null предназначен только для предотвращения ввода пароля и соответствующей обработки, но это не проблема, с которой я сталкиваюсь. Вы правы в том, что функция находится в объекте, но, имея уже собственный валидатор, что мне делать в форме/контроллере, чтобы передать ошибку в форму так же, как UniqueConstrainsts делают в объекте? Я думаю, что если бы это был простой ассерт, установка его в свойстве должна работать, но ассерт какой-то сложный. 14.08.2018
  • Я только что обновил сообщение с пользовательским кодом валидатора. Надеюсь, поможет. 14.08.2018
  • какая версия Symfony? 14.08.2018
  • Версия 3.1, но я планирую обновиться как можно быстрее, когда все недостающие функции, требуемые заказчиком, будут работать. Я не думаю, что есть серьезные изменения или зависимости, поэтому у вас есть предложение, где версия 3.4 или даже 4 является обязательной. Но в любом случае, спасибо за вашу помощь. 14.08.2018
  • попробуйте это: 1 - Удалите @UserAssert\ValidPassword из вашей сущности. 2 - Добавьте эти ограничения в свой Form $ builder = 'constraints' => [new Assert\Length(['min'=>7, 'max'=>50]), new Assert\Regex('/[A-Za-z]/'), new Assert\Regex('/[0-9]/'),] и добавьте use Symfony\Component\Validator\Constraints as Assert; к вашему использованию. Я не знаю, почему вы используете этот шаблон регулярного выражения (только проверяет, существует ли он в первом тесте каждой AZ или AZ и только одна цифра), но .. . 14.08.2018
  • Спасибо, Маркос, за ваш ответ, но я получаю те же результаты: ограничения пароля работают, но результат отображения сообщения об ошибке в форме не меняется. Я проверил, что ошибки попадают в form.errors, но форма не показывает их по умолчанию, как объяснялось выше. Я смотрю на исходный код класса вендор-валидатора, и путь туда по документам другой, т.е. вместо добавления нарушения выдается ошибка через бросок, и это может быть причиной (по крайней мере разница). Может быть, я попробую это завтра. 15.08.2018
  • Поместите код view. Используете ли вы какой-либо генератор, например SensioBundlerGenerator или MarkerBundle? 15.08.2018
  • Я только что обновил сообщение, добавив код ветки. 20.08.2018
  • Проведите тест, используя только {{ form(form) }} в шаблоне ветки, чтобы увидеть, отображаются ли ошибки в другой точке. 20.08.2018

Ответы:


1

ОТВЕТ

Ваш код почти готов. Ваша проблема в том, что вы используете

'error_bubbling' => true

Эта конфигурация изменяет объект для добавления ошибки к целевому родительскому полю или форме. Итак, в вашем случае ошибки в plainPasswordField будут добавлены в форму, а не в поле.

БОЛЬШЕ ИНФОРМАЦИИ

После того, как я провел несколько тестов, я думаю, что есть немного путаницы в ошибках формы и ошибках поля формы.

Если в вашем коде представления нет form_errors(form) или form(form), все form.vars.errors не будут отображаться.

Поля дочерней формы с error_bubbling=true или такими кодами, как:

// Generic Controller
$form->addError(new FormError('My Generic Form Error not associate with any field!'));
return $this->render('my_template.html.twig', [
        'form' => $form->createView(),
    ]);

olny может отображаться в шаблоне ветки с помощью

form_errors(form)

Полезные советы:

  • При создании шаблонов форм отлаживайте представление формы с помощью form(form) (должен быть первый вызов шаблона), чтобы отобразить все в объекте формы, например поля (с вводом HTML-формы | выбор, метка поля, ошибки поля, помощники поля) и ошибки в Сама форма Документ говорит о form_rest(), но не показывает form.vars.errors

  • Используйте form.vars.errors|length для проверки ошибок в переменной представления формы в twig

25.08.2018
  • Спасибо, Маркос. Извините за задержку, но удаление error_bubbling и благодаря вашим объяснениям помогло. Я думаю, что это было начальное состояние, и я добавил его для проверки, но наверняка что-то упустил. Я бы пометил это как решенное, но боюсь, что моя репутация не позволяет мне это сделать, поэтому, пожалуйста, любой администратор, который может это сделать, отметьте это, чтобы это могло помочь любому в такой же ситуации. 21.09.2018
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..