Формы

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

Построение форм

Best Practice

Определяйте ваши формы как PHP-классы.

Компонент Формы позволяет вам строить формы прямо внутри вашего кода контроллера. Это абсолютно норамльно, если вам не нужно использовать форму повторно где-либо ещё. Но для систематизации и повторного использования мы рекомендуем вам определять каждую форму в собственном PHP-классе:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
namespace App\Form;

use App\Entity\Post;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;

class PostType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('summary', TextareaType::class)
            ->add('content', TextareaType::class)
            ->add('authorEmail', EmailType::class)
            ->add('publishedAt', DateTimeType::class)
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Post::class,
        ]);
    }
}

Best Practice

Определите классы типов формы в пространство имён App\Form, разве что вы не используете другие пользовательские классы вроде преобразователей данных.

Чтобы использовать класс, используйте createForm() и передайте полное имя класса:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// ...
use AppBundle\Form\PostType;

// ...
public function newAction(Request $request)
{
    $post = new Post();
    $form = $this->createForm(PostType::class, $post);

    // ...
}

Конфигурация кнопки формы

Классы формы должны пытаться быть независимыми по отношению к тому где они будут использованы. Это делает их повторное использвание позже легче.

Best Practice

Добавляйте кнопки в шаблны, а не в классы форм или контроллеры.

Компонент Форм Symfony позволяет вам добавлять кнопки в качестве полей вашей формы. Это хороший способ упростить шаблон, отображающий вашу форму. Но если вы добавляете кнопки напрямую в ваш класс формы, это сильно ограничит спектр действий этой формы:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class PostType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            // ...
            ->add('save', SubmitType::class, ['label' => 'Create Post'])
        ;
    }

    // ...
}

Эта форма могла быть создана для написания постов, но если бы вы хотели использовать её повторно для редактирования постов, то ярлык кнопки был бы неверным. Вместо этого, некоторые разрботчики конфигурируют кнопки формы в контроллере:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
namespace App\Controller\Admin;

use App\Entity\Post;
use App\Form\PostType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

class PostController extends Controller
{
    // ...

    public function new(Request $request)
    {
        $post = new Post();
        $form = $this->createForm(PostType::class, $post);
        $form->add('submit', SubmitType::class, [
            'label' => 'Create',
            'attr' => ['class' => 'btn btn-default pull-right'],
        ]);

        // ...
    }
}

Это также важная ошибка, так как вы смешиваете разметку презентации (ярлыки, CSS классы и т.д.) с чистым PHP-кодом. Разделение вопросов всегда является хорошей практикой, так что поместите всё, ксающееся просмотра, в слой просмотра:

1
2
3
4
5
6
{{ form_start(form) }}
    {{ form_widget(form) }}

    <input type="submit" value="Create"
           class="btn btn-default pull-right" />
{{ form_end(form) }}

Отображение формы

Существует множество способов отобразить вашу форму, начиная с отображения всего в одной строке, до отображения каждой части каждого поля независимо. Лучший способ зависит от того, какая настраиваемость вам нужна.

Один из наиболее простых способов - который особенно полезен во время разработки - отобразить теги формы и использовать функцию form_widget(), чтобы отобразить все поля:

1
2
3
{{ form_start(form, {attr: {class: 'my-form-class'} }) }}
    {{ form_widget(form) }}
{{ form_end(form) }}

Если вам нужно больше контроля над тем, как отображаются ваши поля, то вам стоит удалить функцию form_widget(form) и отобразить ваши поля по-отдельности. См. How to Customize Form Rendering, чтобы узнать больше информации об этом и о том, как вы можете контролировать то как отображается форма на глоабльном уровне, используя тематизацию форм.

Обработка отправок формы

Обработка отправки формы обычно следует схожему шаблону:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public function new(Request $request)
{
    // построить форму ...

    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($post);
        $em->flush();

        return $this->redirectToRoute('admin_post_show', [
            'id' => $post->getId()
        ]);
    }

    // отобразить шаблон
}

Мы рекомендуем вам использовать одно действие и для отображения формы, и для обработки отправки формы. Например, у вас могло бы быть действие new(), которое только отображает форму, и действией create(), которое только обрабатывает отправку формы. Но эти действия были бы почти идентичными. Намного проще позволить new() делать всё.

Далее: Internationalization

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.