Проверка отправленных форм AJAX в Symfony 5

#php #jquery #ajax #symfony

#php #jquery #ajax #symfony

Вопрос:

Я создаю Address форму в Symfony 5.1.

Он создается в AddressType классе, который имеет некоторые обязательные поля.

 $builder
        ->add('name', TextType::class, [
            'required' => false,
            'label'  => 'address.name',
            'help' => 'address.name_help',
            'attr' => [
                'placeholder' => 'address.name_ph',
            ]
        ])
        ->add('company', TextType::class, [
            'required' => false,
            'label'  => 'address.company',
            'attr' => [
                'placeholder' => 'address.company_ph',
            ]
        ])
        ->add('first_line', TextType::class, [
            'label'  => 'address.first_line',
            'attr' => [
                'placeholder' => 'address.first_line_ph',
            ]
        ])
        ->add('second_line', TextType::class, [
            'required' => false,
            'label'  => 'address.second_line',
            'attr' => [
                'placeholder' => 'address.second_line_ph',
            ]
        ])
        ->add('add_info', TextType::class, [
            'required' => false,
            'label'  => 'address.add_info',
            'help' => 'address.add_info_help',
            'attr' => [
                'placeholder' => 'address.add_info_ph',
            ]
        ])
        ->add('postcode', TextType::class, [
            'label'  => 'address.postcode',
            'attr' => [
                'placeholder' => 'address.postcode_ph',
            ]
        ])
        ->add('city', TextType::class, [
            'label'  => 'address.city',
            'attr' => [
                'placeholder' => 'address.city_ph',
            ]
        ])
        ->add('state', TextType::class, [
            'required' => false,
            'label'  => 'address.state',
            'attr' => [
                'placeholder' => 'address.state_ph',
            ]
        ])
        ->add('country', CountryType::class, [
            'label'  => 'address.country',
            'preferred_choices' => ['FR'],
            'attr' => [
                'data-toggle' => 'select',
                'placeholder' => 'address.country_ph',
            ]
        ])
        ->add('save',
                SubmitType::class,
                [
                    'label'  => $options['submit_btn_label'],
                ]
            );
  

Если я отправляю эту форму с помощью кнопки отправки, все работает как ожидалось, моя форма обрабатывается для проверки, и если она обнаруживает какие-то ошибки, они отображаются в каждом поле.

Вот функция, которая обрабатывает форму :

 public function new(Request $request)
{
    $user = $this->getUser();
    $address = new Address();
    $address->setCreatedBy($user);
    $form = $this->createForm(AddressType::class, $address);
    //handle form
    $form->handleRequest($request);
    if ($form->isSubmitted()){
        //if submit, add hidden fields
        $address = $form->getData();
        //if valid, process
        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($address);
            $em->flush();   

            $this->addFlash(
                'success',
                'Your address was created.'
            );
            return $this->redirectToRoute('address_index');
        }
    } 
    return $this->render('address/new.html.twig', [
        'form' => $form->createView(),
        'mode' => 'new',
    ]);          
}
  

Теперь, если я отправлю эту форму через AJAX-запрос :

 $(document).on('click', '.create-address', function() {
    console.log('submitting new address form...');
    var $form = $(this).closest('form')
    var data = $form.serializeArray();
    $.ajax({
        url : $form.attr('action'),
        type: $form.attr('method'),
        data : data
    });
});
  

В этом случае моя форма обрабатывается для проверки, и она проходит ( $form->isValid() возвращается true ), даже если я не предоставляю некоторые из обязательных полей.
Это приводит к тому, что происходит процесс сохранения объекта, и поэтому я получаю исключение PDOException.

Мой вопрос:
Почему моя форма не обрабатывается одинаково (особенно на этапе проверки) в соответствии с тем, как я отправляю данные?
И насколько отличаются эти два метода с точки зрения функции, которая обрабатывает запрос?

Ответ №1:

required Опция только добавляет required атрибут к разметке. Это заставляет браузер предоставлять значение, но не добавляет никакой проверки на стороне сервера. Вы можете запустить проверку перед вызовом ajax и отправить только в том случае, если статус формы действителен.

Но рекомендуется явно добавить проверку на стороне сервера, используя constraints опцию в форме или аннотируя целевой объект. Обратитесь к документации для получения более подробной информации.

Комментарии:

1. Спасибо за ваш ответ @msg. Я понимаю разницу между обязательным атрибутом и ограничениями. Сущность Address определяется с некоторыми ограничениями, например, not nullable .

2. Хорошо, я на самом деле неправильно понял разницу между ограничениями и правилами ORM. (У меня было правило ORM для полей, не обнуляемых, что, я полагаю, недостаточно / эквивалентно для проверки). Спасибо

3. @Corentoulf Я собирался спросить именно об этом. Однако, начиная с 4.3, они должны генерироваться автоматически .

4. Хм .. Так что это странное поведение, верно? Добавление ограничения в любом случае «принудительно» выполняет проверку.

5. @Corentoulf Я считаю, что лучше быть явным, поэтому я обычно добавляю их в любом случае и не полагаюсь на эту функцию, поэтому я не могу сказать вам наверняка, может быть регрессия. Можете ли вы проверить, установлена ли у вас требуемая зависимость symfony/property-info ? (Я думаю, вам следует, на данный момент это просто любопытство).