Статьи

Сборка и обработка форм в Симфони 2

В этом уроке мы рассмотрим два примера использования форм в Symfony 2. В первом мы поместим элементы формы прямо в файл View, а затем обработаем обработку формы вручную в контроллере. Во втором мы будем использовать систему форм Symfony, чтобы объявлять формы объектно-ориентированным способом, иметь процесс Symfony и сохранять значения.

Мы будем работать над простой установкой фреймворка Symfony. Как вы, возможно, знаете, он поставляется с пакетом по умолчанию, который называется AcmeDemoBundle и мы будем использовать его для иллюстрации работы с формами. Весь окончательный код можно найти в этом репозитории, который я настроил для этого урока. Не стесняйтесь следовать или взглянуть на окончательный код.

Не-сущностные формы

Первый пример, который мы рассмотрим, — это как обрабатывать формы, объявленные как обычные HTML-элементы внутри файла Symfony View. Есть три шага, которые мы предпримем, чтобы проиллюстрировать это:

  1. Мы создадим файл View, который содержит нашу форму HTML
  2. Мы создадим новый метод Controller в классе WelcomeController именем form1Action который будет обрабатывать нашу бизнес-логику (визуализация представления, обработка формы и т. Д.).
  3. Затем мы создадим простую запись маршрута, чтобы отобразить URL-путь к этому методу, чтобы мы могли видеть форму в браузере и иметь возможность отправить ее.

Давайте сначала создадим файл View, который покажет нашу форму и отправленное значение сверху. В файле с именем form1.html.twig расположенном в form1.html.twig src/Acme/DemoBundle/Resources/views/Welcome (соответствующая папка для класса контроллера Welcome Symfony поставляется по умолчанию), у меня есть следующее:

 {% extends "AcmeDemoBundle::layout.html.twig" %} {% block content %} <h1>Form values</h1> {% if name is defined %} <p>Name: {{ name }} </p> {% endif %} <div> <form name="input" action="" method="post"> Name: <input type="text" name="name"/> <input type="submit" name="submit" value="Submit"> </form> </div> {% endblock %} 

Выше я расширяю макет по умолчанию в DemoBundle чтобы не видеть очень белую страницу. А остальное также довольно простое: объявление простой HTML-формы, которая публикует себя и показывает значение единственного текстового поля над формой (которое будет передано из контроллера после обработки в переменной с именем name ).

Далее, давайте объявим метод Controller, отвечающий за отображение этого представления и обработку формы внутри него. В WelcomeController класса WelcomeController я делаю две вещи:

  1. Я использую класс Symfony Request , который поможет нам легко получить доступ к отправленным значениям:

     use Symfony\Component\HttpFoundation\Request; 

    Это выходит за рамки объявления класса.

  2. У меня есть следующий метод:

 public function form1Action() { $post = Request::createFromGlobals(); if ($post->request->has('submit')) { $name = $post->request->get('name'); } else { $name = 'Not submitted yet'; } return $this->render('AcmeDemoBundle:Welcome:form1.html.twig', array('name' => $name)); } 

В этом методе я использую метод createFormGlobals() найденный в объекте $request чтобы собрать createFormGlobals() PHP (включая значения $_POST ). Затем я проверяю, включают ли отправленные значения submit (что по сути является нашей кнопкой отправки), и если они это делают, я извлекаю значение элемента name и передаю его в только что созданное представление. Просто.

Наконец, давайте определим правило маршрутизации, соответствующее URL-пути к этому методу контроллера. В файле routing.yml расположенном в папке src/Acme/DemoBundle/Resources/config я добавил следующее правило:

 _form1: pattern: form1 defaults: { _controller: AcmeDemoBundle:Welcome:form1 } 

Это сопоставит form1/ path с новым методом Controller.

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

Symfony сущности и формы

В дальнейшем мы рассмотрим, как отобразить и обработать форму для сущности Symfony под названием Article (которую я определил тем временем, которую вы можете найти в репозитории). Чтобы узнать, как работают сущности, ознакомьтесь со второй частью этой серии, посвященной платформе Symfony .

Я проиллюстрирую очень простой пример того, как отобразить форму, которая затем сохранит новый объект Article в базу данных, используя способ Symfony . Мы будем работать в основном с 5 файлами: файл класса контроллера, в который мы добавим два новых метода для отображения формы и для отображения простой страницы подтверждения; файл routing.yml так как нам нужно отобразить URL; два Просмотр файлов для отображения формы и подтверждения; и файл ArticleType.php в котором мы создаем форму.

Начнем с последнего. Хотя вы можете создавать форму также непосредственно внутри контроллера, использование отдельного файла типов делает его намного более пригодным для повторного использования, поэтому мы сделаем это вместо этого. Внутри нашей папки src/Acme/DemoBundle/Form меня есть файл ArticleType со следующим содержимым:

 <?php namespace Acme\DemoBundle\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class ArticleType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('title', 'text', array('label' => 'Title')) ->add('body', 'textarea') ->add('save', 'submit'); } public function getName() { return 'article'; } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Acme\DemoBundle\Entity\Article', )); } } 

Выше я расширяю класс конструктора форм Symfony по умолчанию, чтобы определить свою собственную форму. Метод buildForm() отвечает за фактическое построение формы. Внутри я добавляю к объекту $builder различные элементы формы, которые будут соответствовать нашей сущности Article и названы в честь свойств сущности. Для получения дополнительной информации о доступных элементах формы, вы можете обратиться к документации .

Метод getName() просто возвращает имя самого типа формы, тогда как с помощью setDefaultOptions() мы указываем класс сущности, для которого мы используем эту форму (в качестве значения для ключа data_class ). И все, у нас есть определение формы, давайте создадим его внутри нашего контроллера и отобразим на странице.

Вернувшись в класс WelcomeController , я включил в верхние две дополнительные ссылки на классы (для сущности Article и типа формы, которую мы только что создали):

 use Acme\DemoBundle\Entity\Article; use Acme\DemoBundle\Form\ArticleType; 

Далее я добавил следующие два метода:

 public function form2Action(Request $request) { $article = new Article(); $form = $this->createForm(new ArticleType(), $article); $form->handleRequest($request); if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($article); $em->flush(); $session = $this->getRequest()->getSession(); $session->getFlashBag()->add('message', 'Article saved!'); return $this->redirect($this->generateUrl('_form2saved')); } return $this->render('AcmeDemoBundle:Welcome:form2.html.twig', array('form' => $form->createView())); } public function form2savedAction() { return $this->render('AcmeDemoBundle:Welcome:form2saved.html.twig'); } 

Метод form2Action() отвечает за отображение и обработку формы для создания новых объектов Article . Во-первых, он создает новый пустой объект этого класса. Затем он создает новую форму для нее, используя тип формы, который мы определили ранее. Затем он обрабатывает форму, если она была отправлена, но если нет, он form2.html.twig файл вида form2.html.twig View и передает отображаемую HTML-форму для отображения. Давайте сейчас создадим этот файл, а затем вернемся и посмотрим, что происходит с обработкой формы.

Прямо рядом с тем form1.html.twig , где мы создали form1.html.twig , у меня есть form2.html.twig со следующим содержимым:

 {% extends "AcmeDemoBundle::layout.html.twig" %} {% block content %} {{ form(form) }} {% endblock %} 

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

 _form2: pattern: form2 defaults: { _controller: AcmeDemoBundle:Welcome:form2 } 

Теперь мы можем указать нашему браузеру form2/ path и увидеть простую (но довольно некрасивую) форму. Теперь для обработки.

Как мы видели ранее, метод form2Action() имеет переданный ему параметр: объект $request . Поэтому, когда мы отправляем эту форму, она использует метод handleRequest() объекта $form мы создали, чтобы увидеть, была ли форма отправлена ​​(если ее значения существуют в суперглобальных $request ). Если он был отправлен, он выполняет на нем стандартную проверку и сохраняет новый объект в базе данных (тот, который мы изначально создали, был автоматически заполнен значениями формы). Наконец, он сохраняет флэш-сообщение только для одного запроса и перенаправляет на другую страницу, путь строится на основе другого маршрута:

 _form2saved: pattern: form2saved defaults: { _controller: AcmeDemoBundle:Welcome:form2saved } 

Маршрут вызывает метод form2savedAction() который мы объявили в классе WelcomeController и который отображает представление form2saved.html.twig . И в этом представлении все, что я сейчас делаю, это посмотрите, есть ли в сеансе flashBag сообщение и распечатайте его:

 {% extends "AcmeDemoBundle::layout.html.twig" %} {% block content %} {% for flashMessage in app.session.flashbag.get('message') %} <p>{{ flashMessage }}</p> {% endfor %} {% endblock %} 

Вот и все. Теперь вы можете обновить форму и отправить ее. Вы должны быть перенаправлены на простую страницу с сообщением подтверждения. И если вы проверите базу данных, новая запись статьи должна быть сохранена.

Вывод

В этой статье мы рассмотрели очень простое использование системы форм Symfony 2. Сначала мы увидели, как обрабатывать отправку формы, используя обычные элементы формы HTML, напечатанные в представлении. Затем мы увидели, как использовать возможности системы форм Symfony для определения форм в коде, чтобы обрабатывать и сохранять значения как сущность.

Каждый из этих методов имеет свой вариант использования. Если вы выполняете операции CRUD с данными или контентом, лучше всего использовать второй вариант. Symfony очень эффективен, когда дело доходит до абстрагирования ваших данных, и это делает создание форм очень простым. Однако, если вам требуется некоторая обработка формы «на лету», которая ничего не сохраняет, вы можете встроить форму прямо в представление, а затем перехватить отправленные значения в контроллере.

Вопросов? Комментарии? Хочешь узнать больше? Дайте нам знать!