Как настроить отображение формы

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

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

Вспомните, что ярлык, ошибка и HTML-виджет поля формы могут быть легко отображены используя функцию Twig form_row() или метод PHP-помощника row:

  • Twig
    1
    {{ form_row(form.age) }}
    
  • PHP
    1
    <?php echo $view['form']->row($form['age']); ?>
    

Вы также можете отобразить каждую из трёх частей поля индивидуально:

  • Twig
    1
    2
    3
    4
    5
    <div>
        {{ form_label(form.age) }}
        {{ form_errors(form.age) }}
        {{ form_widget(form.age) }}
    </div>
    
  • PHP
    1
    2
    3
    4
    5
    <div>
        <?php echo $view['form']->label($form['age']); ?>
        <?php echo $view['form']->errors($form['age']); ?>
        <?php echo $view['form']->widget($form['age']); ?>
    </div>
    

В обоих случаях, ярлык, ошибки и HTML-виджет формы отображаются, используя набор разметок, которые поставляются в стандартной Symfony. Например, оба вышеописанных шаблона отобразят:

1
2
3
4
5
6
7
<div>
    <label for="form_age">Age</label>
    <ul>
        <li>This field is required</li>
    </ul>
    <input type="number" id="form_age" name="form[age]" />
</div>

Чтобы быстро создать прототип и протестировать форму, вы можете отобразить всю форму с помощью одной строки:

  • Twig
    1
    2
    3
    4
    5
    {# отображает все поля #}
    {{ form_widget(form) }}
    
    {# отображает все поля *и* начальные и финальные теги формы #}
    {{ form(form) }}
    
  • PHP
    1
    2
    3
    4
    5
    <!-- отображает все поля -->
    <?php echo $view['form']->widget($form) ?>
    
    <!-- отображает все поля *и* начальные и финальные теги формы -->
    <?php echo $view['form']->form($form) ?>
    

Оставшаяся часть этого рецепта объяснит, как может быть изменена каждая часть разметки формы на разных уровнях. Чтобы узнать больше об отображении форм в целом, смотрите How to Control the Rendering of a Form.

Что такое темы форм?

Symfony использует фрагменты форм - маленькая часть шаблона, которая отображает только одну часть формы - чтобы отображать каждую часть формы - ярлыки полей, ошибки, текстовые поля input, теги select, и т.д.

Фрагменты определяются как блоки в Twig и как файлы шаблонов в PHP.

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

Symfony поставляется с некоторыми встроенными темами форм, которые определяют каждый фрагмент, необходимый для отображения всех частей формы:

  • form_div_layout.html.twig, оборачивает каждое поле формы внутри элемента <div>.
  • form_table_layout.html.twig, оборачивает всю форму внутри элемента <table> и каждое поле формы внутри элемента <tr>.
  • bootstrap_3_layout.html.twig, оборачивается каждое поле формы внутри элемента <div> с соответствующими CSS-классами, чтобы применить стили Bootstrap 3 CSS framework по умолчанию.
  • bootstrap_3_horizontal_layout.html.twig, похож на предыдущую тему, но применяеымые CSS-классы те, которые используются для отображения форм горизонтально (т.е. ярлык и виджет в одном ряду).
  • foundation_5_layout.html.twig, оборачивает каждое поле формы внутри элемента <div> с соответствующими CSS-классами, чтобы применить стили Foundation CSS framework по умолчанию.

Caution

Когда вы используете темы форм Bootstrap и отображаете поля вручную, вызов form_label() для поля флажка/радио ничего не покажет. Из-за внутренних процессов Bootstrap, ярлык уже отображён form_widget().

В следующем разделе вы узнаете, как настроить темы, переопределим некоторые или все её фрагменты.

Например, когда отображается виджет типа поля integer, генерируется поле input number.

  • Twig
    1
    {{ form_widget(form.age) }}
    
  • PHP
    1
    <?php echo $view['form']->widget($form['age']) ?>
    

отображает:

1
<input type="number" id="form_age" name="form[age]" required="required" value="33" />

Внутренне, Symfony использует фрагмент integer_widget, чтобы отобразить поле. Это потому, что тип поля - integer и вы отображаете его widget (вместо его label или errors).

В Twig это по умолчанию будет блоком integer_widget из шаблона form_div_layout.html.twig.

В PHP это скорее будет файлом integer_widget.html.php, находящимся в папке FrameworkBundle/Resources/views/Form.

По умолчанию, реализация фрагмента integer_widget выглядит так:

  • Twig
    1
    2
    3
    4
    5
    {# form_div_layout.html.twig #}
    {% block integer_widget %}
        {% set type = type|default('number') %}
        {{ block('form_widget_simple') }}
    {% endblock integer_widget %}
    
  • PHP
    1
    2
    <!-- integer_widget.html.php -->
    <?php echo $view['form']->block($form, 'form_widget_simple', array('type' => isset($type) ? $type : "number")) ?>
    

Как вы видите, этот фрагмент сам отображает другой фрагмент - form_widget_simple:

  • Twig
    1
    2
    3
    4
    5
    {# form_div_layout.html.twig #}
    {% block form_widget_simple %}
        {% set type = type|default('text') %}
        <input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
    {% endblock form_widget_simple %}
    
  • PHP
    1
    2
    3
    4
    5
    6
    <!-- FrameworkBundle/Resources/views/Form/form_widget_simple.html.php -->
    <input
        type="<?php echo isset($type) ? $view->escape($type) : 'text' ?>"
        <?php if (!empty($value)): ?>value="<?php echo $view->escape($value) ?>"<?php endif ?>
        <?php echo $view['form']->block($form, 'widget_attributes') ?>
    />
    

Суть в том, что фрагменты диктуют HTML-вывод каждой части формы. Чтобы настроить вывод формы, вам просто нужно идентифицировать и переопределить правильный фрагмент. Набор таких модификаций фрагментов форм известен как "тема" формы. При отображении формы, вы можете выбрать, какую(ие) тему(ы) формы вы хотите применить.

В Twig, тема - это один файл щаблона, а фрагменты - блоки, определённые в этом файле.

В PHP, тема - это папка, а фрагменты - индивидуальные файлы щаблона в этой папке.

В этом примере, имя настраиваемого фрагмента - integer_widget так как вы хотите переопределить HTML widget для всех типов поля integer. Если вам нужно настроить поля textarea, то вы будете изменять textarea_widget.

Часть integer походит от имени класса: IntegerType становится integer, что основано на стандартах.

Как вы можете увидеть, имя фрагмента - это комбинация типа поля и того, какая часть поля отображается (например, widget, label, errors, row). По существу, чтобы отобразить, как отображаются ошибки только для полей ввода text, вам нужно настроить фрагмент text_errors.

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

Чтобы получить больше информации по этой теме, смотрите Именование фрагментов шаблона.

Темизация форм

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

Темизация форм в Twig

При настройке блока поля формы в Twig, у вас есть два варианта того, где может жить настраиваемый блок формы:

+--------------------------------------+-----------------------------------+----------------------------------------------==-------+ | Метод | Плюсы | Минусы | +======================================+===================================+=======================================================+ | Внутри того же шаблона, что и форма | Быстро и легко | Не может быть повторно использовано в других шаблонах | +--------------------------------------+-----------------------------------+-------------------------------------------------------+ | Внутри отдельного шаблона | Может быть использован много раз | Требует создание дополнительного шаблона | +--------------------------------------+-----------------------------------+-------------------------------------------------------+

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

Метод 1: Внутри того же шаблона, что и форма

Наиболее лёгкий способ настроить блок integer_widget - это настроить его напрямую в шаблоне, который отображает форму.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{% extends 'base.html.twig' %}

{% form_theme form _self %}

{% block integer_widget %}
    <div class="integer_widget">
        {% set type = type|default('number') %}
        {{ block('form_widget_simple') }}
    </div>
{% endblock %}

{% block content %}
    {# ... отобразить форму #}

    {{ form_row(form.age) }}
{% endblock %}

Ипользуя специальный тег {% form_theme form _self %}, Twig ищет внутри тех же шаблонов любые переопределённые блоки формы. Если предположить, что поле form.age - это тип поля integer, то когда отображается его виджет, будет использован настраиваемый блок integer_widget.

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

Метод 2: Внутри отдельного шаблона

Вы также можете решить разместить настраиваемый блок формы integer_widget в отдельном шаблоне. Код и финальный результат будут одинаковыми, но теперь вы можете использовать настройку формы повторно во многих шаблонах:

1
2
3
4
5
6
7
{# app/Resources/views/form/fields.html.twig #}
{% block integer_widget %}
    <div class="integer_widget">
        {% set type = type|default('number') %}
        {{ block('form_widget_simple') }}
    </div>
{% endblock %}

Теперь, когда вы содали настроенный блок формы, вам нужно сообщить Symfony, чтобы она использовала его. Внутри шаблона, где вы отображаете вашу форму, скажите Symfony использовать шаблон с помощью тега form_theme:

1
2
3
{% form_theme form 'form/fields.html.twig' %}

{{ form_widget(form.age) }}

Когда отображается виджет form.age, Symfony будет использовать блок integer_widget из нового шаблона, а тег input будет обёрнут в элемент div, указаный в настроенном блоке.

Несколько шаблонов

Форма также может быть настроена путём применения нескольких шаблонов. Чтобы сделать это, передайте имя всех щаблонов в качестве массива, используя ключевое слово with:

1
2
3
{% form_theme form with ['common.html.twig', 'form/fields.html.twig'] %}

{# ... #}

Шаблоны также могут находиться в разных пакетах, используйте функционально имя, чтобы сослаться на такие шаблоны, например, AcmeFormExtraBundle:form:fields.html.twig.

Дочерние формы

Вы также можете применить тему формы к конкретной дочери вашей формы:

1
{% form_theme form.child 'form/fields.html.twig' %}

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

1
2
3
{% form_theme form 'form/fields.html.twig' %}

{% form_theme form.child 'form/fields_child.html.twig' %}

Темизация форм в PHP

При использовании шаблонизатора PHP, единственный способ настроить фрагмент - это создать новый файл шаблона, что похоже на второй метод, используемый в Twig.

Файл шаблона должен быть назван в честь фрагмента. Вы должны создать файл integer_widget.html.php, чтобы настроить фрагмент integer_widget.

1
2
3
4
5
6
7
8
<!-- app/Resources/views/form/integer_widget.html.php -->
<div class="integer_widget">
    <?php echo $view['form']->block(
        $form,
        'form_widget_simple',
        array('type' => isset($type) ? $type : "number")
    ) ?>
</div>

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

1
2
3
<?php $view['form']->setTheme($form, array(':form')); ?>

<?php $view['form']->widget($form['age']) ?>

При отображении виджета form.age, Symfony будет использовать настроенный шаблон integer_widget.html.php и тег input будет обёрнут в элемент div.

Если вы хотите применить тему к конкретной дочерней форме, передайте её в метод
setTheme():
1
<?php $view['form']->setTheme($form['child'], ':form'); ?>

Note

Синтаксис :form основывается на функциональных именах для шаблонов: Bundle:Directory. Так как каталог формы живёт в каталоге app/Resources/views, часть Bundle пуста, что приводит к :form.

Referencing base Form Blocks (Twig specific)

So far, to override a particular form block, the best method is to copy the default block from form_div_layout.html.twig, paste it into a different template, and then customize it. In many cases, you can avoid doing this by referencing the base block when customizing it.

This is easy to do, but varies slightly depending on if your form block customizations are in the same template as the form or a separate template.

Referencing Blocks from inside the same Template as the Form

Import the blocks by adding a use tag in the template where you're rendering the form:

1
{% use 'form_div_layout.html.twig' with integer_widget as base_integer_widget %}

Now, when the blocks from form_div_layout.html.twig are imported, the integer_widget block is called base_integer_widget. This means that when you redefine the integer_widget block, you can reference the default markup via base_integer_widget:

1
2
3
4
5
{% block integer_widget %}
    <div class="integer_widget">
        {{ block('base_integer_widget') }}
    </div>
{% endblock %}

Ссылание на базовые блоки из внешнего шаблона

Если ваши настройки находятся во внешнем шаблоне, вы можете сослаться на базовый блок, используя функцию Twig parent():

1
2
3
4
5
6
7
8
{# app/Resources/views/form/fields.html.twig #}
{% extends 'form_div_layout.html.twig' %}

{% block integer_widget %}
    <div class="integer_widget">
        {{ parent() }}
    </div>
{% endblock %}

Note

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

Создание настроек для всего приложения

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

Twig

Используя следующую конфигурацию, любые изменённые блоки форм внутри шаблона form/fields.html.twig будут использованы глобально при отображении формы.

  • YAML
    1
    2
    3
    4
    5
    # app/config/config.yml
    twig:
        form_themes:
            - 'form/fields.html.twig'
        # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    <!-- app/config/config.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:twig="http://symfony.com/schema/dic/twig"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/twig
            http://symfony.com/schema/dic/twig/twig-1.0.xsd">
    
        <twig:config>
            <twig:form-theme>form/fields.html.twig</twig:form-theme>
            <!-- ... -->
        </twig:config>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    8
    // app/config/config.php
    $container->loadFromExtension('twig', array(
        'form_themes' => array(
            'form/fields.html.twig',
        ),
    
        // ...
    ));
    

По умолчанию, Twig использует макет div при отображении форм. Однако, некоторые люди могут предпочесть отображение форм в макете таблицы. Используйте ресурс form_table_layout.html.twig, чтобы использовать такой макет:

  • YAML
    1
    2
    3
    4
    5
    # app/config/config.yml
    twig:
        form_themes:
            - 'form_table_layout.html.twig'
        # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    <!-- app/config/config.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:twig="http://symfony.com/schema/dic/twig"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/twig
            http://symfony.com/schema/dic/twig/twig-1.0.xsd">
    
        <twig:config>
            <twig:form-theme>form_table_layout.html.twig</twig:form-theme>
            <!-- ... -->
        </twig:config>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    8
    // app/config/config.php
    $container->loadFromExtension('twig', array(
        'form_themes' => array(
            'form_table_layout.html.twig',
        ),
    
        // ...
    ));
    

Если вы хотите сделать измнения только в одном шаблоне, добавьте следующую строку в ваш файл шаблона, вместо того, чтобы добавлять шаблон в качестве ресурса:

1
{% form_theme form 'form_table_layout.html.twig' %}

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

PHP

Используя следующую конфигурацию, любые настроенные фрагменты формы внутри папке app/Resources/views/Form будут использованы глобально при отображении формы.

  • YAML
    1
    2
    3
    4
    5
    6
    7
    # app/config/config.yml
    framework:
        templating:
            form:
                resources:
                    - 'AppBundle:Form'
        # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <!-- app/config/config.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <framework:config>
            <framework:templating>
                <framework:form>
                    <framework:resource>AppBundle:Form</framework:resource>
                </framework:form>
            </framework:templating>
            <!-- ... -->
        </framework:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    // app/config/config.php
    // PHP
    $container->loadFromExtension('framework', array(
        'templating' => array(
            'form' => array(
                'resources' => array(
                    'AppBundle:Form',
                ),
            ),
         ),
    
         // ...
    ));
    

По умолчанию, механизм PHP использует макет div при отображении форм. Однако, некоторые люди могут предпочесть отображение форм в макете таблицы. Используйте ресурс FrameworkBundle:FormTable, чтобы использовать такой макет:

  • YAML
    1
    2
    3
    4
    5
    6
    # app/config/config.yml
    framework:
        templating:
            form:
                resources:
                    - 'FrameworkBundle:FormTable'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <!-- app/config/config.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <framework:config>
            <framework:templating>
                <framework:form>
                    <resource>FrameworkBundle:FormTable</resource>
                </framework:form>
            </framework:templating>
            <!-- ... -->
        </framework:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    // app/config/config.php
    $container->loadFromExtension('framework', array(
        'templating' => array(
            'form' => array(
                'resources' => array(
                    'FrameworkBundle:FormTable',
                ),
            ),
        ),
    
         // ...
    ));
    

Если вы хотите сделать измнения только в одном шаблоне, добавьте следующую строку в ваш файл шаблона, вместо того, чтобы добавлять шаблон в качестве ресурса:

1
<?php $view['form']->setTheme($form, array('FrameworkBundle:FormTable')); ?>

Отметьте, что переменная $form в коде выше - это переменная просмотра формы, которую вы передали в ваш шаблон.

Как настроить отдельное поле

До этого моменты, вы видели разные способы настройки вывода виджета всех типов текстовых полей. Вы также можете настраивать отдельные поля. Например, представьте, что у вас есть два поля text в форме product - name и description - но вы хотите настроить только одно из них. Это можно сделать, настроит фрагмент, имя которого является комбинацией атрибута поля id и указания того, какая часть поля будет настроена. Например, чтобы настроить только поле name:

  • Twig
    1
    2
    3
    4
    5
    6
    7
    8
    9
    {% form_theme form _self %}
    
    {% block _product_name_widget %}
        <div class="text_widget">
            {{ block('form_widget_simple') }}
        </div>
    {% endblock %}
    
    {{ form_widget(form.name) }}
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <!-- Главный шаблон -->
    <?php echo $view['form']->setTheme($form, array(':form')); ?>
    
    <?php echo $view['form']->widget($form['name']); ?>
    
    <!-- app/Resources/views/form/_product_name_widget.html.php -->
    <div class="text_widget">
        <?php echo $view['form']->block('form_widget_simple') ?>
    </div>
    

Здесь, фрагмент _product_name_widget определяет, какой шаблон использоваться для поля, id которого - product_name (а имя - product[name]).

Tip

Часть поля product - это имя формы, которое может быть установлено вручную или сгенерированно автоматически, в зависимости от имения типа вашей формы (например, ProductType приравнивается к product). Если вы не уверены в имени вашей формы, просто посмотрите источник вашей сгенерированной формы.

Если вы хотите изменить часть product или name в имени блока _product_name_widget, то вы можете установить опцию block_name в вашем типе формы:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;

public function buildForm(FormBuilderInterface $builder, array $options)
{
    // ...

    $builder->add('name', TextType::class, array(
        'block_name' => 'custom_name',
    ));
}

Тогда имя блока будет _product_custom_name_widget.

Вы также можете переопределить разметку всей строки поля, используя такой же метод:

  • Twig
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    {% form_theme form _self %}
    
    {% block _product_name_row %}
        <div class="name_row">
            {{ form_label(form) }}
            {{ form_errors(form) }}
            {{ form_widget(form) }}
        </div>
    {% endblock %}
    
    {{ form_row(form.name) }}
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    <!-- Главный шаблон -->
    <?php echo $view['form']->setTheme($form, array(':form')); ?>
    
    <?php echo $view['form']->row($form['name']); ?>
    
    <!-- app/Resources/views/form/_product_name_row.html.php -->
    <div class="name_row">
        <?php echo $view['form']->label($form) ?>
        <?php echo $view['form']->errors($form) ?>
        <?php echo $view['form']->widget($form) ?>
    </div>
    

Как настроить прототип коллекции

При использовании коллекции форм, прототип может быть переопределён полностью настроенным вами прототипом, путём переопределения блока. Например, если ваше поле формы называется tasks, вы сможете изменить виджет каждой задачи (task) следующим образом:

  • Twig
    1
    2
    3
    4
    5
    6
    7
    8
    {% form_theme form _self %}
    
    {% block _tasks_entry_widget %}
        <tr>
            <td>{{ form_widget(form.task) }}</td>
            <td>{{ form_widget(form.dueDate) }}</td>
        </tr>
    {% endblock %}
    
  • PHP
    1
    2
    3
    4
    5
    <!-- src/AppBundle/Resources/views/Form/_tasks_entry_widget.html.php -->
    <tr>
        <td><?php echo $view['form']->widget($form->task) ?></td>
        <td><?php echo $view['form']->widget($form->dueDate) ?></td>
    </tr>
    

Вы можете не только переопределить отображённый виджет, но также изменить полностью строку формы или ярлык. Для данного выше поля tasks, имена блоков будут такими:

Часть формы Имя блока
label _tasks_entry_label
widget _tasks_entry_widget
row _tasks_entry_row

Другие общие настройки

До этого момента, здесь было показано несколько разных способов настроить одну часть того, как отображается форма. Главное - настроить конкретный фрагмент, который соответствует части формы, которую вы хотите контролировать (смотрите именование блоков формы).

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

Настройка вывода ошибки

Note

Компонент Формы работает только с тем как отображаются ошибки валидации, а не с самими сообщениями об ошибке валидации. Сообщения об ошибках определяются ограничениями валидации, которые вы применяете к вашим объектам. Чтобы узнать больше, смотрите статью о ваидации.

Существует множество разных способов настроить то, как отображаются ошибки, когда форма отправлена с ошибками. Сообщения об ошибке поля отображаются, когда вы используете помощник``form_errors()``:

  • Twig
    1
    {{ form_errors(form.age) }}
    
  • PHP
    1
    <?php echo $view['form']->errors($form['age']); ?>
    

По умолчанию, ошибки отображаются в виде неупорядоченного списка:

1
2
3
<ul>
    <li>This field is required</li>
</ul>

Чтобы переопределить то, как отображаются ошибки для всех полей, просто скопируйте, вставьте и настройте фрагмент form_errors.

  • Twig
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    {# form_errors.html.twig #}
    {% block form_errors %}
        {% spaceless %}
            {% if errors|length > 0 %}
            <ul>
                {% for error in errors %}
                    <li>{{ error.message }}</li>
                {% endfor %}
            </ul>
            {% endif %}
        {% endspaceless %}
    {% endblock form_errors %}
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    8
    <!-- form_errors.html.php -->
    <?php if ($errors): ?>
        <ul>
            <?php foreach ($errors as $error): ?>
                <li><?php echo $error->getMessage() ?></li>
            <?php endforeach ?>
        </ul>
    <?php endif ?>
    

Tip

Смотрите Темизация форм, чтобы узнать, как применить эту настройку.

Вы также можете настроить вывод ошибок только для одного конкретного поля. Чтобы настроить только разметку, используемую для этих ошибок, следуйте тем же инструкциям, что и выше, но поместите содержимое в относительный блок _errors (или файл, в случае PHP-шаблонов). Например, text_errors (или text_errors.html.php).

Tip

Смотрите Именование фрагментов шаблона, чтобы узнать, какой именно блок или файл вам нужно настроить.

Некоторые ошибки, более глобальные для вашей формы (т.е. не относятся конкретно к одному полю), отображаются отдельно, обычно сверху в вашей форме:

  • Twig
    1
    {{ form_errors(form) }}
    
  • PHP
    1
    <?php echo $view['form']->render($form); ?>
    

Чтобы настроить только разметку, используемую для этих ошибок, следуйте тем же инструкциям, что и выше, но проверьте, установлена ли переменная compound, как true, это означает, что то, что сейчас отображается - является коллекцией полей (например, целой формой). а не просто отдельным полем.

  • Twig
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    {# form_errors.html.twig #}
    {% block form_errors %}
        {% spaceless %}
            {% if errors|length > 0 %}
                {% if compound %}
                    <ul>
                        {% for error in errors %}
                            <li>{{ error.message }}</li>
                        {% endfor %}
                    </ul>
                {% else %}
                    {# ... display the errors for a single field #}
                {% endif %}
            {% endif %}
        {% endspaceless %}
    {% endblock form_errors %}
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    <!-- form_errors.html.php -->
    <?php if ($errors): ?>
        <?php if ($compound): ?>
            <ul>
                <?php foreach ($errors as $error): ?>
                    <li><?php echo $error->getMessage() ?></li>
                <?php endforeach ?>
            </ul>
        <?php else: ?>
            <!-- ... render the errors for a single field -->
        <?php endif ?>
    <?php endif ?>
    

Настройка "строки формы"

Когда вы научитесь с этим управляться, наиболее простым способом отобразить поле формы будет через функцию form_row(), которая отображает ярлык, ошибки и HTML-виджет поля. Чтобы настроить разметку, используемую для отображения всех строк полей формы, переопределите фрагмент form_row. Например, представьте, что вы хотите добавить класс к элементу div в каждой строке:

  • Twig
    1
    2
    3
    4
    5
    6
    7
    8
    {# form_row.html.twig #}
    {% block form_row %}
        <div class="form_row">
            {{ form_label(form) }}
            {{ form_errors(form) }}
            {{ form_widget(form) }}
        </div>
    {% endblock form_row %}
    
  • PHP
    1
    2
    3
    4
    5
    6
    <!-- form_row.html.php -->
    <div class="form_row">
        <?php echo $view['form']->label($form) ?>
        <?php echo $view['form']->errors($form) ?>
        <?php echo $view['form']->widget($form) ?>
    </div>
    

Tip

Смотрите Темизация форм, чтобы узнать, как применить эту настройку.

Добавление "обязательного" символа звёздочки в ярлыки полей

Если вы хотите обозначить все ваши обязательные поля с помощью символя звёздочки (*), вы можете сделать это, настроив фрагмент form_label.

В Twig, если делаете настройку формы внутри того же шаблона, что и ваша форма, модифицируйте тег use и добавьте следующее:

1
2
3
4
5
6
7
8
9
{% use 'form_div_layout.html.twig' with form_label as base_form_label %}

{% block form_label %}
    {{ block('base_form_label') }}

    {% if required %}
        <span class="required" title="This field is required">*</span>
    {% endif %}
{% endblock %}

В Twig, если вы делаете настройку формы в отдельном шаблоне, используйте следующее:

1
2
3
4
5
6
7
8
9
{% extends 'form_div_layout.html.twig' %}

{% block form_label %}
    {{ parent() }}

    {% if required %}
        <span class="required" title="This field is required">*</span>
    {% endif %}
{% endblock %}

При использовании механизма шаблонов PHP, вам нужно скопировать содержание из первоисходного шаблона:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<!-- form_label.html.php -->

<!-- оригинальное содержимое -->
<?php if ($required) { $label_attr['class'] = trim((isset($label_attr['class']) ? $label_attr['class'] : '').' required'); } ?>
<?php if (!$compound) { $label_attr['for'] = $id; } ?>
<?php if (!$label) { $label = $view['form']->humanize($name); } ?>
<label <?php foreach ($label_attr as $k => $v) { printf('%s="%s" ', $view->escape($k), $view->escape($v)); } ?>><?php echo $view->escape($view['translator']->trans($label, array(), $translation_domain)) ?></label>

<!-- настройка -->
<?php if ($required) : ?>
    <span class="required" title="This field is required">*</span>
<?php endif ?>

Tip

Смотрите Темизация форм, чтобы узнать, как применить эту настройку.

По умолчанию, теги label в обязательных полях, отображаются с CSS-классом required. Поэтому, вы можете добавить символ звёздочки используя только CSS:

1
2
3
label.required:before {
    content: "* ";
}

Добавление сообщений "помощи"

Вы также можете настроить ваши виджеты формы так, чтобы они имели необязательное сообщение "помощи".

В Twig, если вы делаете настройки формы внутри того же шаблона, что и форма, модифицируйте тег use и добавьте следующее:

1
2
3
4
5
6
7
8
9
{% use 'form_div_layout.html.twig' with form_widget_simple as base_form_widget_simple %}

{% block form_widget_simple %}
    {{ block('base_form_widget_simple') }}

    {% if help is defined %}
        <span class="help-block">{{ help }}</span>
    {% endif %}
{% endblock %}

В Twig, если вы делаете настройки формы внутри отдельного шаблона, используйте следующее:

1
2
3
4
5
6
7
8
9
{% extends 'form_div_layout.html.twig' %}

{% block form_widget_simple %}
    {{ parent() }}

    {% if help is defined %}
        <span class="help-block">{{ help }}</span>
    {% endif %}
{% endblock %}

При использовании механизма шаблонов PHP, вам нужно скопировать содержание из первоисходного шаблона:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<!-- form_widget_simple.html.php -->

<!-- Оригинальное содержание -->
<input
    type="<?php echo isset($type) ? $view->escape($type) : 'text' ?>"
    <?php if (!empty($value)): ?>value="<?php echo $view->escape($value) ?>"<?php endif ?>
    <?php echo $view['form']->block($form, 'widget_attributes') ?>
/>

<!-- Настройка -->
<?php if (isset($help)) : ?>
    <span class="help"><?php echo $view->escape($help) ?></span>
<?php endif ?>

Чтобы отобразить сообщение помощи внизу поля, передайте переменную help:

  • Twig
    1
    {{ form_widget(form.title, {'help': 'foobar'}) }}
    
  • PHP
    1
    <?php echo $view['form']->widget($form['title'], array('help' => 'foobar')) ?>
    

Tip

Смотрите Темизация форм, чтобы узнать, как применить эту настройку.

Использование переменных формы

Большинство функций, доступных для отображения разных частей формы (например, виджет формы, ярлык формы, ошибки формы и т.д.) также позволяют вам делать некоторые настройки напрямую. Посмотрите на следующий пример:

  • Twig
    1
    2
    {# отобразить виджет, но добавить к нему класс "foo" #}
    {{ form_widget(form.name, { 'attr': {'class': 'foo'} }) }}
    
  • PHP
    1
    2
    3
    4
    5
    6
    <!-- отобразить виджет, но добавить к нему класс "foo" -->
    <?php echo $view['form']->widget($form['name'], array(
        'attr' => array(
            'class' => 'foo',
        ),
    )) ?>
    

Массив, переданный в качестве второго аргумента, содержит "переменные" формы. Чтобы узнать больше об этом концепте Twig, смотрите More about Form Variables.

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