Как установить значение по умолчанию для поля формы в Symfony2?

109

Есть ли простой способ установить значение по умолчанию для текстового поля?

  • 1
    да, но ответы на этот вопрос не удовлетворяют / не работают ... Я добавлю "Изменить", чтобы объяснить, почему :-)
  • 0
    Кажется, что «идеальное» решение, которое вы ищете, для поля иметь опцию «default_value». Дело в том, что в настоящее время это не так, поэтому я не думаю, что идеальное решение, которое вы ищете в настоящее время, существует. Единственное, что предоставляет Symfony (см. Ссылку), это опция data. Таким образом, если-то это единственный подход, который я вижу. Даже если бы в самом поле была опция default_value, я думаю, что в любом случае она по сути делала бы то же самое внутри.
Показать ещё 5 комментариев
Теги:

20 ответов

95
Лучший ответ

Можно легко использовать при создании:

->add('myfield', 'text', array(
     'label' => 'Field',
     'data' => 'Default value'
))
  • 10
    Для Symfony 2.1 мне нужно было изменить ключ 'data' на 'value'
  • 2
    @ Ты уверен? Просто попытался value в Symfony 2.1.5-DEV - не получилось. Но data работали просто отлично.
Показать ещё 5 комментариев
93

вы можете установить значение по умолчанию с помощью empty_data

$builder->add('myField', 'number', ['empty_data' => 'Default value'])
  • 29
    Данные настройки не являются настройками по умолчанию. Этот ответ правильный.
  • 9
    Похоже, что для поля устанавливается только 1, когда оно отправлено без значения. Как насчет того, когда вы хотите, чтобы в форме по умолчанию отображалось 1 во вводе, когда значение отсутствует?
Показать ещё 1 комментарий
51

Я размышлял об этом несколько раз в прошлом, поэтому подумал, что буду записывать различные идеи, которые я использовал/использовал. Что-то может быть полезно, но ни один из них не является идеальным решением Symfony2.

Конструктор В Entity вы можете сделать $this- > setBar ( "значение по умолчанию" ); но это вызывается каждый раз, когда вы загружаете объект (db или нет) и немного беспорядочно. Однако он работает для каждого типа поля, поскольку вы можете создавать даты или что-то еще, что вам нужно.

Если утверждения в get Я бы не хотел, но ты мог.

return ( ! $this->hasFoo() ) ? 'default' : $this->foo;

Factory/instance. Вызвать статическую функцию/вторичный класс, который предоставляет вам по умолчанию Entity, предварительно заполненную данными. Например.

function getFactory() {
    $obj = new static();
    $obj->setBar('foo');
    $obj->setFoo('bar');

   return $obj;
}

Не идеально, если вам нужно будет поддерживать эту функцию, если вы добавите дополнительные поля, но это означает, что вы разделяете настройки данных/по умолчанию и то, что генерируется из db. Аналогичным образом, вы можете иметь несколько getFactories, если вам нужны разные данные по умолчанию.

Объекты Extended/Reflection Создайте расширяющийся Entity (например, FooCreate extends Foo), который дает вам данные по умолчанию во время создания (через конструктор). Подобно идее Factory/instance просто другой подход - я предпочитаю статические методы лично.

Установить данные перед формой сборки В конструкторах/службах вы знаете, есть ли у вас новый объект или если он был заполнен из db. Поэтому представляется правдоподобным для вызова заданных данных по различным полям при захвате нового объекта. Например.

if( ! $entity->isFromDB() ) {
     $entity->setBar('default');
     $entity->setDate( date('Y-m-d');
     ...
}
$form = $this->createForm(...)

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

Расширенные формы Подобно событиям Form, но вы вызываете другой тип в зависимости от того, является ли это db/new entity. Под этим я подразумеваю, что у вас есть FooType, который определяет вашу форму редактирования, BarType расширяет FooType и устанавливает все данные в поля. В вашем контроллере вы просто выбираете, какой тип формы нужно инициировать. Это отстой, если у вас есть пользовательская тема, хотя и, как события, создает слишком много обслуживания по своему вкусу.

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

form_widget(form.foo, {attr: { value : default } });

JS Было бы тривиально заполнять форму функцией JS, если поля пустые. Например, вы могли бы что-то сделать с помощью заполнителей. Это плохая, плохая идея.

Формы как службы Для одного из проектов на основе больших форм я создал службу, которая генерировала все формы, делала всю обработку и т.д. Это было связано с тем, что формы должны использоваться на нескольких контроллерах в нескольких средах, и в то время как формы были сгенерированы/обработаны таким же образом они отображались/взаимодействовали по-разному (например, обработка ошибок, перенаправления и т.д.). Красота такого подхода заключалась в том, что вы можете использовать данные по умолчанию, делать все, что вам нужно, обрабатывать ошибки в целом и т.д., И все они инкапсулированы в одном месте.

Заключение Как я вижу, вы снова столкнетесь с той же проблемой снова и снова - где живут данные по умолчанию?

  • Если вы храните его на уровне db/doctrine, что произойдет, если вы не хотите сохранять значение по умолчанию каждый раз?
  • Если вы сохраните его на уровне Entity, что произойдет, если вы хотите повторно использовать этот объект в другом месте без каких-либо данных?
  • Если вы сохраните его на уровне Entity и добавьте новое поле, вы хотите, чтобы предыдущие версии имели это значение по умолчанию при редактировании? То же самое касается значения по умолчанию в БД...
  • Если вы храните его на уровне формы, это очевидно, когда вы приходите для поддержки кода позже?
  • Если это в конструкторе, что произойдет, если вы используете форму в нескольких местах?
  • Если вы нажмете его на уровень JS, вы зашли слишком далеко - данные не должны быть в представлении, а не в JS (и мы игнорируем совместимость, ошибки рендеринга и т.д.).
  • Сервис отличный, если я использую его в нескольких местах, но он переполняет простую форму добавления/редактирования на одном сайте...

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

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

Удачи! Надеюсь, я дал вам хоть какую-то пищу для размышлений, и не слишком сильно перебирал;)

  • 0
    Не могли бы вы немного подробнее рассказать о том, что вы имели в виду под «сервисом, который генерировал все формы»? Я также сейчас работаю над действительно ориентированным на форму проектом, и было бы здорово иметь разные точки зрения на него.
  • 2
    при использовании доктрины конструкторы не вызываются, когда сущность загружается из БД.
36

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

// buildForm() method
public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder
    ...
    ->add(
        'myField',
        'text',
        array(
            'data' => isset($options['data']) ? $options['data']->getMyField() : 'my default value'
        )
    );
}

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

  • 0
    В случае массивов вместо сущностей просто замените $options['data']->getMyField() на $option['data']['myField']
  • 2
    Я думаю, что это правильный путь для добавления / обновления. Но я ненавижу, что Symfony слишком усложняет.
19

Вы можете установить значение по умолчанию для связанного поля в классе модели (в определении отображения или установить значение самостоятельно).

Кроме того, FormBuilder дает вам возможность установить начальные значения с помощью метода setData(). Конструктор форм передается методу createForm() вашего класса формы.

Также проверьте эту ссылку: http://symfony.com/doc/current/book/forms.html#using-a-form-without-a-class

16

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

public function __construct()
{
    $this->field = 'default value';
}
  • 0
    Тем не менее, ваша форма может иметь дополнительные поля, которые не могут быть сопоставлены с вашей сущностью ( 'mapped' => false ). Используйте setData(...) для них.
11

Подход 1 (из http://www.cranespud.com/blog/dead-simple-default-values-on-symfony2-forms/)

Просто установите значение по умолчанию в своей сущности либо в объявлении переменной, либо в конструкторе:

class Entity {
    private $color = '#0000FF';
    ...
}

или

class Entity {
    private $color;

    public function __construct(){
         $this->color = '#0000FF';
         ...
    }
    ...
}

Подход 2 из комментария в приведенной выше ссылке, а также ответ Dmitriy (не принятый) из Как установить значение по умолчанию для поля формы в Symfony2?

Добавьте значение по умолчанию в атрибут данных при добавлении поля с помощью FormBuilder, адаптированного из ответа Дмитрия.

Обратите внимание, что это предполагает, что свойство будет иметь и будет иметь значение null, когда оно представляет собой новую, а не существующую сущность.

public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder->add('color', 'text', array(
            'label' => 'Color:',
            'data' => (isset($options['data']) && $options['data']->getColor() !== null) ? $options['data']->getColor() : '#0000FF'
        )
    );
}
  • 0
    Первый работает (спасибо!), Второй - нет (для меня): $ options ["data] всегда устанавливается, поэтому значение по умолчанию никогда не будет использоваться. Мне все еще интересно, является ли решение номер 1 намеченным способом сделать это...
  • 0
    Вы правы, что $ options ['data'] всегда устанавливается. Если вы не инициализируете поле сущности, вы можете вместо этого проверить его на ноль, например. 'data' => $ options ['data'] -> getColor ()! == null? и т. д. Это предполагает, что нулевое значение не является допустимым значением для цветового поля, поэтому существующие сущности никогда не будут иметь нулевое значение для этого поля.
Показать ещё 2 комментария
9

Вы можете установить значение по умолчанию, например. для формы message, например:

$defaultData = array('message' => 'Type your message here');
$form = $this->createFormBuilder($defaultData)
    ->add('name', 'text')
    ->add('email', 'email')
    ->add('message', 'textarea')
    ->add('send', 'submit')
    ->getForm();

Если ваша форма сопоставлена ​​с Entity, вы можете пойти так (например, имя пользователя по умолчанию):

$user = new User();
$user->setUsername('John Doe');

$form = $this->createFormBuilder($user)
    ->add('username')
    ->getForm();
  • 2
    Я предпочитаю этот метод, особенно потому, что в большинстве приложений вы создаете форму и передаете сущность, с которой имеет дело форма.
7

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

class FormTypeExtension extends AbstractTypeExtension
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        if (null !== $options['default']) {
            $builder->addEventListener(
                FormEvents::PRE_SET_DATA,
                function (FormEvent $event) use ($options) {
                    if (null === $event->getData()) {
                        $event->setData($options['default']);
                    }
                }
            );
        }
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefault('default', null);
    }

    public function getExtendedType()
    {
        return FormType::class;
    }
}

и зарегистрируйте расширение формы:

app.form_type_extension:
    class: AdminBundle\Form\Extension\BootstrapAdminFormTypeExtension
    tags:
        - { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType }

После этого мы можем использовать опцию default в любом поле формы:

$formBuilder->add('user', null, array('default' => $this->getUser()));
$formBuilder->add('foo', null, array('default' => 'bar'));
  • 0
    Это должно было быть принято как лучший ответ (актуальный)
5
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
     $form = $event->getForm(); 
     $data = $event->getData(); 

     if ($data == null) {
         $form->add('position', IntegerType::class, array('data' => 0));
     }

});
  • 0
    это хорошее решение. Вызов $event->setData() вместо чтения поля может сделать его еще лучше.
4

Если вы используете FormBuilder в symfony 2.7 для создания формы, вы также можете передать исходные данные методу createFormBuilder элемента управления

$values = array(
    'name' => "Bob"
);

$formBuilder = $this->createFormBuilder($values);
$formBuilder->add('name', 'text');
4

Именно поэтому я понимаю проблему.

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

Лично я считаю, что решение @MolecularMans - это путь. Я бы фактически установил значения по умолчанию в конструкторе или в заявлении свойства. Но вам, похоже, не нравится этот подход.

Вместо этого вы можете выполнить следующее: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html

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

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

3

Существует очень простой способ: вы можете установить значения по умолчанию:

$defaults = array('sortby' => $sortby,'category' => $category,'page' => 1);

$form = $this->formfactory->createBuilder('form', $defaults)
->add('sortby','choice')
->add('category','choice')
->add('page','hidden')
->getForm();
3

Часто для значений init по умолчанию для формы я используются приборы. Потому что этот способ не самый легкий, но очень удобный.

Пример:

class LoadSurgeonPlanData implements FixtureInterface
{
    public function load(ObjectManager $manager)
    {
        $surgeonPlan = new SurgeonPlan();

        $surgeonPlan->setName('Free trial');
        $surgeonPlan->setPrice(0);
        $surgeonPlan->setDelayWorkHours(0);
        $surgeonPlan->setSlug('free');

        $manager->persist($surgeonPlan);
        $manager->flush();        
    }   
}

Тем не менее, поле типа symfony имеет опцию data.

Пример

$builder->add('token', 'hidden', array(
    'data' => 'abcdef',
));
3

Мое решение:

$defaultvalue = $options['data']->getMyField();
$builder->add('myField', 'number', array(
            'data' => !empty($defaultvalue) ? $options['data']->getMyField() : 0
        )) ;
1

Если вы установите "данные" в своей форме создания, это значение не будет изменено при редактировании вашей сущности.

Мое решение:

public function buildForm(FormBuilderInterface $builder, array $options) {
    // In my example, data is an associated array
    $data = $builder->getData();

    $builder->add('myfield', 'text', array(
     'label' => 'Field',
     'data' => array_key_exits('myfield', $data) ? $data['myfield'] : 'Default value',
    ));
}

Bye.

  • 0
    Гораздо полезнее, чем принятый ответ! Если вы используете PHP7 +, вы можете сделать его еще лучше с помощью: 'data' => $data['myfield'] ?? 'Default value',
1

Обычно я обычно устанавливаю значение по умолчанию для определенного поля в моей сущности:

/**
 * @var int
 * @ORM\Column(type="integer", nullable=true)
 */
protected $development_time = 0;

Это будет работать для новых записей или только для обновления существующих.

  • 0
    Это не работает, когда 'empty_data' является обратным вызовом, используется для разрешения параметров конструктора на объекте.
1

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

Пример:

public function getMyField() {
    if (is_null($this->MyField)) {
        $this->setMyField('my default value');
    }
    return $this->MyField;
}
1

Значения по умолчанию устанавливаются путем настройки соответствующего объекта. Прежде чем привязать объект к форме, установите его цветовое поле в "# 0000FF":

// controller action
$project = new Project();
$project->setColor('#0000FF');
$form = $this->createForm(new ProjectType(), $project);
  • 0
    этот подход работает, но имеет тот недостаток, что вы должны делать это каждый раз, когда используете класс формы, и он очень многословен (множество операторов set). Поскольку компонент формы очень элегантен, должно быть что-то еще. Но все равно спасибо :-)
  • 0
    @ jamie0726 По моему мнению, контроллер должен устанавливать значения объекта всякий раз, когда он новый или выбранный. Таким образом, вы можете использовать форму в разных ситуациях с разным поведением, например, новый цвет может измениться из-за того, что у пользователя есть менеджер или роль супер-менеджера, а поскольку это бизнес-логика, которая должна контролироваться Контроллер или сервис, а не форма. Поэтому, как сказал Серад, я тоже предпочитаю это решение. Вы всегда можете создать службу, чтобы установить эти значения по умолчанию, и в контроллере использовать эту службу, сохраняя ее СУХОЙ.
Показать ещё 1 комментарий
-1

Как сказал Брайан:

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

вы можете установить значение по умолчанию с помощью empty_value

$builder->add('myField', 'number', ['empty_value' => 'Default value'])

Ещё вопросы

Сообщество Overcoder
Наверх
Меню