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


137

Чи існує простий спосіб встановити значення за замовчуванням для поля текстової форми?


1
так, але відповіді, дані в цьому питанні, не задовольняють / не працюють ... Я додам "Редагувати", щоб пояснити, чому :-)
herrjeh42

Здається, що «ідеальне» рішення, яке ви шукаєте, полягає в тому, що в полі є варіант «значення_значення за умовчанням». Річ у тому, що наразі це не так, тому я не думаю, що ідеального рішення, яке ви шукаєте, наразі існує. Єдине, що надає symfony (див. Посилання) - це параметр даних. Тож if-then - це єдиний підхід, який я можу бачити atm. Навіть якби на самому полі була опція 'default_value', я думаю, що це все-таки все одно зробить все те саме.
crysallus

Крім того, я вніс виправлення своєї відповіді у підході 2 відповідно до моїх коментарів під нею. Якщо це вирішує проблему з синтаксисом, яку ви згадали у пункті 2, ви можете відредагувати цей коментар. Або дайте мені знати, в чому полягає проблема, і я виправлю свою відповідь.
crysallus

1
@Crone це запитання було задано 2 роки раніше
Ondrej Slinták

1
@ OndrejSlinták Я не голосував за те, щоб закрити як дуп, але FYI: не важливо, хто з них прийшов першим: " Якщо нове запитання є кращим питанням або має кращі відповіді, тоді голосуйте, щоб закрити старе як дублікат" нового ".
Джефф Пукетт

Відповіді:


105

Можна легко використовувати під час створення із:

->add('myfield', 'text', array(
     'label' => 'Field',
     'empty_data' => 'Default value'
))

11
Для Symfony 2.1 мені потрібно було змінити 'data'ключ на'value'
Edd

175
Це не тільки встановлює значення за замовчуванням, воно також завжди примушує це значення в будь-якому контексті. Не те, що я б назвав "значенням за замовчуванням" ...
Хуберт Перрон

4
Я підтримав це рішення, оскільки це не є вирішенням проблеми (як згадував Губерт Перрон вище). Я намагаюся отримати краще рішення в цьому пості stackoverflow.com/questions/17986481 / ...
herrjeh42

13
Це початкове значення, значення за замовчуваннямempty_data
Pierre de LESPINAY,

3
dataмарний - він перезаписує збережене значення. empty_dataне показує значення, воно використовує його при надсиланні порожнього значення і унеможливлює збереження неперевірених варіантів.
ліплення

115

ви можете встановити значення за замовчуванням за допомогою empty_data

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

29
Налаштування даних не встановлює значення за замовчуванням. Ця відповідь є правильною.
Олексій Теніцький

9
Здається, це поле встановлює лише 1, коли воно подано без значення. А як щодо того, коли ви хочете, щоб форма за замовчуванням відображала 1 на вході, коли значення немає?
Брайан

У моєму тестуванні empty_data не дозволяє мені змінювати значення за замовчуванням з поля, поданого порожнім, наприклад, якщо ви хочете зберегти в базі даних 0 як замість NULL. Ця помилка залишається видатною, наскільки я можу сказати: github.com/symfony/symfony/isissue/5906
Chadwick Meyer

63

Я думав про це кілька разів у минулому, тому думав, що я сформулюю різні ідеї, які мав / використовував. Щось може бути корисним, але жодне не є "ідеальним" рішенням Symfony2.

Конструктор В Entity ви можете зробити $ this-> setBar ('значення за замовчуванням'); але це називається кожен раз, коли ви завантажуєте сутність (db чи ні) і трохи заплутано. Однак це працює для кожного типу поля, оскільки ви можете створювати дати або все, що вам потрібно.

Якщо твердження в get отримати я не став би, але ви могли.

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

Фабрика / екземпляр . Викличте статичну функцію / вторинний клас, який надає вам об'єкт за замовчуванням, попередньо заповнений даними. Напр

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

   return $obj;
}

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

Розширені / Відображаючі об'єкти Створіть об'єкт, що розширюється (наприклад, FooCreate розширює Foo), який дає вам дані про дефолт під час створення (через конструктор). Подібно до фабричної / екземплярної ідеї просто інший підхід - я віддаю перевагу статичним методам особисто.

Встановлення даних перед формою збірки У конструкторах / службі ви знаєте, чи є у вас новий об'єкт чи він був заповнений з db. Тому правдоподібно викликати набір даних у різних полях, коли ви захоплюєте нову сутність. Напр

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

Події форми При створенні форми ви встановлюєте дані за замовчуванням під час створення полів. Ви користуєтеся цим використанням слухача подій PreSetData. Проблема з цим полягає в тому, що ви дублюєте код завантаження / дублювання коду форми і ускладнюєте їх підтримку / розуміння.

Розширені форми, подібні до подій форми, але ви називаєте різного типу залежно від того, чи є це db / new сутність. Під цим я маю на увазі, що у вас є FooType, який визначає вашу форму редагування, BarType розширює FooType це і встановлює всі дані на поля. Потім у своєму контролері ви просто вибираєте, який тип форми запровадити. Це гарно, якщо у вас є власна тема, хоча і, як події, створює занадто багато обслуговування для мого вподобання.

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

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

JS Було б тривіально заповнити форму функцією JS, якщо поля порожні. Ви можете щось зробити, наприклад, із заповнювачами. Це все-таки погана, погана ідея.

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

Висновок Як я бачу, ви знову і знову будете стикатися з тим самим питанням - де жити дані про дефолт?

  • Якщо ви зберігаєте його на рівні db / doctrine, що станеться, якщо ви не хочете щоразу зберігати за замовчуванням?
  • Якщо ви зберігаєте його на рівні Entity, що станеться, якщо ви хочете повторно використовувати це об'єкт в іншому місці без будь-яких даних?
  • Якщо ви зберігаєте його на рівні сутності та додаєте нове поле, чи хочете, щоб попередні версії мали це значення за замовчуванням при редагуванні? Те саме стосується і за замовчуванням у БД ...
  • Якщо ви зберігаєте його на рівні форми, це очевидно, коли ви пізніше підтримуєте код?
  • Якщо це в конструкторі, що станеться, якщо ви використовуєте форму в декількох місцях?
  • Якщо ви підштовхнете його до рівня JS, то ви зайшли занадто далеко - дані не повинні переглядати JS (і ми ігноруємо сумісність, відображаємо помилки тощо)
  • Сервіс чудовий, якщо, як я, ви використовуєте його в декількох місцях, але це надмірно для простого додавання / редагування форми на одному сайті ...

З цією метою я щоразу підходив до проблеми по-різному. Наприклад, параметр форми реєстрації "бюлетень" легко (і логічно) встановлюється в конструкторі безпосередньо перед створенням форми. Коли я створював колекції форм, які були пов'язані між собою (наприклад, які перемикачі в різних типах форм пов’язані між собою), то я використовував слухачів подій. Коли я створив складнішу сутність (наприклад, таку, яка вимагає дітей або багато даних про дефолт), я використовував функцію (наприклад, 'getFactory'), щоб створити її елемент, як мені це потрібно.

Я не думаю, що існує один "правильний" підхід, оскільки кожен раз, коли у мене була ця вимога, вона була дещо іншою.

Удачі! Я сподіваюся, що я дав тобі трохи їжі для роздумів і не надто сильно пом'ятав;)


Ви можете трохи детальніше розповісти про те, що ви мали на увазі про «послугу, яка створила всі форми»? Я зараз також працюю над проектом, орієнтованим на форму, і зараз було б чудово по-різному.
користувач2268997

2
при використанні доктрини конструктори не викликаються, коли сутність завантажується з db.
NDM

43

Якщо вам потрібно встановити значення за замовчуванням, і ваша форма стосується сутності, слід скористатися наступним підходом:

// 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завжди буде встановлено значення за замовчуванням, замість отримання значення від сутності.


У разі масивів замість сут, просто замініть $options['data']->getMyField()на$option['data']['myField']
ggg

3
Це правильний спосіб як додавання / оновлення, я думаю. Але я ненавиджу Symfony зробити його занадто складним.
Ярко

Це єдина хороша відповідь. Я не розумію інших відповідей, коли дивлюсь на док. empty_data: Цей параметр визначає, яке значення поверне поле, коли подане значення буде порожнім. Він не встановлює початкового значення
Вінсент Деко

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';
}

Незважаючи на це, у вашій формі можуть бути додаткові поля, які не будуть відображені у вашій сутності ( 'mapped' => false). Використовуйте setData(...)для цього.
Дізлі

12

Підхід 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 з коментаря у вищенаведеному посиланні, а також відповідь Дмитра (не прийнята) із розділу Як встановити значення за замовчуванням для поля форми в 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'
        )
    );
}

Перший працює (спасибі!), Другий - не (для мене): $ options ["data] завжди встановлено, тому значення за замовчуванням ніколи не буде використане. Мені все ще цікаво, чи рішення 1 - це призначений шлях зробити це ...
herrjeh42

Ви маєте рацію щодо налаштувань $ options ['data'], які завжди встановлюються. Якщо ви не ініціалізуєте поле сутності, ви можете замість цього тестувати поле, наприклад, поле. 'data' => $ options ['data'] -> getColor ()! == null? і т.д. ... Це передбачає, що null не є дійсним значенням для кольору кольору, тому існуючі сутності ніколи не матимуть нульового значення для цього поля.
crysallus

ах, дурний мені: я спробував це з 'isset ($ $ options [' data '] -> getColor ())', я отримав повідомлення про помилку про "використання його в написанні контекстів не дозволено" і забув, що я повинен перевірити це інакше :-)
herrjeh42

1
Насправді, здається, бувають випадки, коли введення даних не встановлено. Безпечніше тестувати обидва значення isset ($ options ['data']) && options options ['data'] -> getColor ()! == null? ...
crysallus

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();

У випадку, якщо ваша форма відображена в об'єкті, ви можете перейти так (наприклад, ім'я користувача за замовчуванням):

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

$form = $this->createFormBuilder($user)
    ->add('username')
    ->getForm();

2
Я віддаю перевагу цьому методу, тим більше, що в більшості додатків ви створюєте форму та передаєте особу, якою займається форма.
прокручено

9

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

// src/Form/Extension/DefaultFormTypeExtension.php

class DefaultFormTypeExtension 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: App\Form\Extension\DefaultFormTypeExtension
    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'));

Це повинно було бути прийнято як найкращу відповідь (актуальну)
medunes

7

Не використовувати:

'data' => 'Default value'

Читайте тут: https://symfony.com/doc/current/reference/forms/types/form.html#data

"Опція даних завжди переосмислює значення, взяте з даних домену (об'єкта) під час надання. Це означає, що значення об'єкта також перевизначається, коли форма редагує вже збережений об'єкт, внаслідок чого він втрачає збережене значення під час подання форми."


Використовуйте наступне:

Скажімо, для цього прикладу у вас є Entity Foo, і є поле "активне" (у цьому прикладі є CheckBoxType, але процес такий же, як і для всіх інших типів), яке ви хочете перевірити за замовчуванням

У ваш клас FooFormType додайте:

...
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
...
public function buildForm( FormBuilderInterface $builder, array $options )
{
    ...

    $builder->add('active', CheckboxType::class, array(
        'label' => 'Active',
    ));

    $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        function(FormEvent $event){                 
            $foo = $event->getData();
            // Set Active to true (checked) if form is "create new" ($foo->active = null)
            if(is_null($foo->getActive())) $foo->setActive(true);
        }
   );
}
public function configureOptions( OptionsResolver $resolver )
{
    $resolver->setDefaults(array(
        'data_class' => 'AppBundle:Foo',
    ));
}

Це ось гроші !! Використовуйте прослуховувач подій форми, щоб перевірити свої значення перед тим, як дефолтувати їх. Це має бути прийнятою відповіддю для значень, що не мають значень у ваших формах, оскільки вони працюють як для нових дій, так і для редагування дій.
tlorens

Це правильний спосіб впоратися з цим, і це має бути прийнятою відповіддю.
Беттінц

Те, що ви згадуєте на початку, не відповідає дійсності, якщо ви використовуєте умовний / потрійний. 'data' => $data['myfield'] ?? 'Default value'
Ось так

6
->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));
     }

});

це приємне рішення. Виклик $event->setData()замість читання поля може зробити це ще краще.
користувач2268997

5

Моє рішення:

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

4

Просто так я розумію проблему.

Ви хочете скорегувати спосіб побудови форми на основі даних у вашій сутності. Якщо сутність створюється, використовуйте якесь значення за замовчуванням. Якщо сутність існує, використовуйте значення бази даних.

Особисто я думаю, що рішення @ MolecularMans - це шлях. Я б фактично встановив значення за замовчуванням в конструкторі або в операторі властивості. Але вам, здається, такий підхід не подобається.

Натомість ви можете слідувати цьому: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html

Ви повісите слухача на тип вашої форми, а потім зможете вивчити свою сутність та відкоригувати програму-> відповідно додати заяви на основі havine нової чи існуючої сутності. Вам все ще потрібно десь вказати значення за замовчуванням, хоча ви можете просто кодувати їх у своєму слухачі. Або передати їх у тип форми.

Схоже, багато роботи, хоча. Краще просто передати об'єкт у форму із уже встановленими значеннями за замовчуванням.


4

Якщо ви використовуєте FormBuilderin symfony 2.7 для генерування форми, ви також можете передати початкові дані createFormBuilderметоду контролера

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

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

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 має параметри даних .

Приклад

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

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

Якщо ви встановите "дані" у формі створення, це значення не змінюватиметься під час редагування вашої сутності.

Моє рішення:

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',
    ));
}

До побачення.


Набагато корисніша, ніж прийнята відповідь! Якщо ви використовуєте PHP7 +, ви можете зробити його ще більш 'data' => $data['myfield'] ?? 'Default value',
охайним

У вас є помилка друку у функції array_key_exists ()
Deadpool

1

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

// controller action
$project = new Project();
$project->setColor('#0000FF');
$form = $this->createForm(new ProjectType(), $project);

такий підхід працює, але має той недолік, що ви повинні робити це кожного разу, коли ви використовуєте клас форми, і це дуже багатослівно (багато заданих висловлювань). Оскільки компонент форми дуже елегантний, має бути щось інше. Але все-таки спасибі :-)
herrjeh42

@ jamie0726 На мій погляд, відповідальність контролера встановлює значення об'єкта, коли він новий або вилучений. Таким чином, ви можете використовувати форму, яка використовується в різних ситуаціях з різною поведінкою, наприклад, новий колір може змінитися через те, що користувач має роль менеджера або керівника суперменеджера, а оскільки це ділова логіка, яку слід контролювати контролер чи послуга, а не форма. Тому, як заявив Серад, я також віддаю перевагу цьому рішенню. Ви завжди можете створити службу для встановлення цих значень за замовчуванням, а в контролері використовувати цю службу, зберігаючи її ДУХО.
saamorim

Це рішення, яке я обрав, бо воно відповідає логіці, на яку я думаю. Згенеровані контролери мають різні методи створення форм EDIT і CREATE, і саме там я встановлюю дані за замовчуванням / початкові дані для нової сутності.
alumi

1

Якщо це поле пов'язане з сутністю (є властивістю цієї сутності), ви можете просто встановити для нього значення за замовчуванням.

Приклад:

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

1

Зазвичай я просто встановлюю значення за замовчуванням для конкретного поля моєї сутності:

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

Це буде працювати для нових записів або просто оновлення існуючих.


Схоже, це не працює, коли 'empty_data'використовується зворотний виклик, щоб дозволити параметри конструктора на об'єкті.
НДМ

1

Коли Брайан запитав:

Здається, що порожні_дані встановлюють поле лише 1, коли воно подано без значення. Що робити, коли ви хочете, щоб форма за замовчуванням відображала значення 1 на вході, коли значення немає?

ви можете встановити значення за замовчуванням за допомогою empty_value

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

0

Я вирішив цю проблему шляхом додавання значення в ATTR :

->add('projectDeliveringInDays', null, [
    'attr' => [
          'min'=>'1',
          'value'=>'1'
          ]
     ])
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.