Symfony2のフォームフィールドのデフォルト値を設定する方法


137

テキストフォームフィールドのデフォルト値を設定する簡単な方法はありますか?


1
はい、しかし、この質問で与えられた答えは満足のいくものではありません/機能しません...私は理由を説明するために「編集」を追加します:-)
herrjeh42

あなたが求めている「完璧な」解決策は、フィールドに「default_value」オプションがあることのようです。物事は、現在はそうではないので、あなたが探している完璧な解決策は現在存在しているとは思いません。symfonyが提供する唯一のもの(リンクを参照)データオプションです。したがって、if-thenがatmで確認できる唯一のアプローチです。フィールド自体に「default_value」オプションがあったとしても、基本的には内部的には同じことを本質的に実行すると思います。
crysallus 2013

また、アプローチ2での私のコメントに従って、回答を修正しました。ポイント2で述べた構文の問題が修正された場合は、そのコメントを編集することをお勧めします。または問題が何であるかを知らせてください、そして私は私の答えを修正します。
crysallus 2013

1
@Croneこの質問は2年前に尋ねられました
OndrejSlinták2016

1
OndrejSlinták私はFYIだまされやすい人としてのいずれかで閉じ、それに投票しなかった@:それは、どちらが最初に来た問題ではない" 新しい質問が重複したとして、古いものを閉じるために投票、より良い質問があるか、より良い答えを持っている場合新しいものの。
Jeff Puckett

回答:


105

作成中に簡単に使用できます:

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

11
Symfony 2.1では、'data'キーを'value'
Edd

175
これはデフォルト値を設定するだけでなく、常にあらゆる状況下で値を強制します。私が「デフォルト値」と呼ぶものではありません...
Hubert Perron、2013

4
(Hubert Perronが前述したように)問題の解決策ではないため、私はこの解決策に反対票を投じました。私はこの記事では、よりよい解決策取得しようとしていますstackoverflow.com/questions/17986481/...
herrjeh42

13
これは初期値で、デフォルト値はempty_data
Pierre de LESPINAY

3
data役に立たない-保存された値を上書きします。empty_data値は表示されません。空の値の送信時に使用され、チェックされていない選択肢を保存することができなくなります。
モールドクラフト2017

115

デフォルト値を設定できます empty_data

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

29
設定データはデフォルトを設定していません。これが正解です。
Alexei Tenitski 14

9
これは、値なしで送信された場合にのみフィールドを1に設定するように見えます。値が存在しないときにフォームの入力にデフォルトで1を表示する場合はどうでしょうか?
ブライアン

私のテストでは、empty_dataを使用して、空に送信されたフィールドのデフォルト値を上書きできません。たとえば、データベースにNULLではなく0として保存する場合などです。このバグは、私が知る限り、まだ未解決です:github.com/symfony/symfony/issues/5906
Chadwick Meyer

63

私はこれを過去に何度か考えたことがあります。そのため、これまでに使用したさまざまなアイデアを書き留めておきます。何かが役に立つかもしれませんが、「完璧な」Symfony2ソリューションはありません。

コンストラクター エンティティでは、$ this-> setBar( 'default value');を実行できます。しかし、これはエンティティ(dbかどうかに関係なく)を読み込むたびに呼び出され、少し面倒です。ただし、日付やその他の必要なものを作成できるため、すべてのフィールドタイプで機能します。

get内のステートメント はそうしませんが、できます。

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

ファクトリ/インスタンス。データが事前入力されたデフォルトのエンティティを提供する静的関数/セカンダリクラスを呼び出します。例えば

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

   return $obj;
}

余分なフィールドを追加する場合にこの機能を維持する必要があるため、実際には理想的ではありませんが、データセッター/デフォルトとデータベースから生成されるデータセッターを分離することを意味します。同様に、異なるデフォルトのデータが必要な場合は、複数のgetFactoriesを使用できます。

拡張/リフレクションエンティティ 拡張エンティティ(FooCreate extends Fooなど)を作成します。これにより、作成時に(コンストラクタを介して)デフォルトのデータが提供されます。ファクトリー/インスタンスのアイデアと同様に、異なるアプローチ-私は静的メソッドを個人的に好みます。

ビルドフォームの前にデータを設定 コンストラクター/サービスで、新しいエンティティがあるかどうか、またはそれがdbから入力されたかどうかがわかります。したがって、新しいエンティティを取得するときに、さまざまなフィールドのセットデータを呼び出すのがもっともです。例えば

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

フォームイベント を作成するとき、フィールドを作成するときにデフォルトのデータを設定します。これをオーバーライドするには、PreSetDataイベントリスナーを使用します。これの問題は、フォームのワークロードを複製したり、コードを複製したりして、維持/理解を困難にすることです。

拡張 フォームFormイベントに似ていますが、db /新しいエンティティであるかどうかに応じて異なるタイプを呼び出します。これは、編集フォームを定義するFooTypeがあることを意味します。BarTypeはこれをFooTypeに拡張し、すべてのデータをフィールドに設定します。次にコントローラーで、起動するフォームタイプを選択するだけです。ただし、カスタムテーマがあり、イベントが好きな場合、これは私の好みではメンテナンスが多すぎます。

小枝 フィールドごとに行う場合、独自のテーマを作成し、値オプションを使用してデータをデフォルト設定することもできます。テンプレートをクリーンに保ち、フォームを再利用できるようにしたい場合でも、これをフォームテーマにラップすることを妨げるものはありません。例えば

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

JS フィールドが空の場合、フォームにJS関数を入力するのは簡単です。たとえば、プレースホルダーを使用して何かを行うことができます。しかし、これは悪い、悪い考えです。

サービスとしてのフォーム 私が行った大きなフォームベースのプロジェクトの1つすべてのフォームを生成し、すべての処理などを行うサービスを作成しました。これは、フォームが複数の環境の複数のコントローラー間で使用され、同じ方法で生成/処理され、表示/操作方法が異なります(エラー処理、リダイレクトなど)。このアプローチの優れた点は、データのデフォルト設定、必要なすべての処理、一般的なエラーの処理などを行うことができ、すべてが1か所にカプセル化されていることです。

結論 ご覧のとおり、同じ問題が何度も発生します。デフォルトのデータはどこに保存されますか?

  • これをdb / doctrineレベルで保存した場合、毎回デフォルトを保存したくない場合はどうなりますか?
  • エンティティレベルで保存した場合、そのエンティティをデータなしで他の場所で再利用したい場合はどうなりますか?
  • エンティティレベルで保存して新しいフィールドを追加する場合、編集時に以前のバージョンにデフォルト値を設定しますか?DBのデフォルトにも同じことが言えます...
  • フォームレベルで保存する場合、後でコードを保守するようになったときにそれは明らかですか?
  • コンストラクター内にある場合、フォームを複数の場所で使用するとどうなりますか?
  • それをJSレベルにプッシュすると、あなたは行き​​過ぎました-データはビューに表示されるべきではなく、JSを気にする必要はありません(そして互換性、レンダリングエラーなどを無視しています)
  • 私のように複数の場所で使用している場合、サービスは素晴らしいですが、1つのサイトで単純な追加/編集フォームを作成するには過剰です...

そのために、私は毎回異なる方法で問題に取り組みました。たとえば、サインアップフォームの「ニュースレター」オプションは、フォームを作成する直前にコンストラクターで簡単に(かつ論理的に)設定できます。一緒にリンクされたフォームコレクション(たとえば、さまざまなフォームタイプのどのラジオボタンが一緒にリンクされているか)を作成していたとき、イベントリスナーを使用しました。より複雑なエンティティ(たとえば、子または多くのデフォルトデータが必要なエンティティ)を構築したとき、必要に応じて関数(たとえば、「getFactory」)を使用して要素を作成しました。

私はこの要件があるたびに少し異なるため、「正しい」アプローチは1つとは思いません。

幸運を!とにかく私があなたに考えさせるための食べ物を与えて、あまり騒ぎすぎなかったことを願っています;)


「すべてのフォームを生成するサービス」について、もう少し詳しく教えてもらえますか?本当にフォーム中心のプロジェクトにも取り組んでいるので、さまざまな視点を持っているといいですね。
user2268997 14

2
doctrineを使用する場合、エンティティが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が複雑すぎると嫌いです。
Yarco 2017年

これが唯一の良い答えです。ドキュメントを見ると、他の回答がわかりません。empty_data:このオプションは、送信された値が空の場合にフィールドが返す値を決定します。初期値は設定しません
Vincent Decaux

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(...)これらに使用します。
ディズリー2013年

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のフォームフィールドのデフォルト値を設定する方法からの Dmitriyの回答(受け入れられたものではありません)

Dmitriyの回答を基に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'
        )
    );
}

最初のものは機能します(ありがとう!)、2つ目は機能しません(私にとっては):$ options ["data]は常に設定されているため、デフォルト値は使用されません。それを行うには...
herrjeh42 2013

$ options ['data']が常に設定されるのはあなたの言うとおりです。エンティティフィールドを初期化しない場合は、代わりにフィールドのnullをテストできます。'data' => $ options ['data']-> getColor()!== null?etc ...これは、nullがカラーフィールドの有効な値ではないと想定しているため、既存のエンティティがそのフィールドにnull値を持つことはありません。
crysallus 2013

ああ、愚かな私: 'isset($ $ options [' data ']-> getColor())'で試してみたところ、「コンテキストの書き込みでの使用は許可されていません」というエラーメッセージが表示され、別の方法で確認してください:-)
herrjeh42 2013

1
実際には、データエントリが設定されていない場合があります。つまり、両方をテストする方が安全ですisset($ options ['data'])&& $ options ['data']-> getColor()!== null?...
crysallus 2013

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
特に、ほとんどのアプリケーションではフォームを作成し、フォームが処理するエンティティを渡すため、この方法を使用します。
14

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 2017

7

使用しないでください:

'data' => 'Default value'

こちらをお読みください:https : //symfony.com/doc/current/reference/forms/types/form.html#data

「データオプションは、レンダリング時に常にドメインデータ(オブジェクト)から取得した値をオーバーライドします。これは、フォームが既に永続化されているオブジェクトをフォームが編集すると、オブジェクト値もオーバーライドされ、フォームが送信されたときに永続化された値が失われることを意味します。」


以下を使用します。

この例の場合、エンティティ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

これはこれを処理する正しい方法であり、これが受け入れられた答えになるはずです。
Bettinz

条件付き/三項を使用する場合、最初に述べたことは正しくありません。このように:'data' => $data['myfield'] ?? 'Default value'
xarlymg89

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()の代わりに、フィールドをreaddingは、それがさらに良くなるかもしれません。
user2268997

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

リスナーをフォームタイプにぶら下げて、エンティティを調べ、新しいエンティティまたは既存のエンティティに基づいて、それに応じてbuilder-> addステートメントを調整できます。デフォルト値をリスナーでコーディングすることもできますが、どこかにデフォルト値を指定する必要があります。または、フォームタイプに渡します。

しかし、多くの作業のようです。デフォルト値がすでに設定されているエンティティをフォームに渡すだけの方が良いでしょう。


4

あなたが使用している場合はFormBuilder、フォームを生成するためにはsymfony 2.7で、あなたはまた、初期データを渡すことができるcreateFormBuilderのcontrolerの方法

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

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

3

多くの場合、フォームの初期値には、フィクスチャを使用します。当然のことながら、この方法は簡単ではありませんが、非常に快適です。

例:

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のtypeフィールドにはオプションdataがあります。

$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',
Boykodev

array_key_exists()関数にタイプミスがある
Deadpool

1

デフォルト値は、対応するエンティティを構成することによって設定されます。エンティティをフォームにバインドする前に、その色フィールドを「#0000FF」に設定します。

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

このアプローチは機能しますが、フォームクラスを使用するたびに実行する必要があるという欠点があり、非常に冗長です(多くのsetステートメント)。フォームコンポーネントは非常にエレガントなので、何か他のものがあるはずです。とにかくありがとう:-)
herrjeh42 2013

@ jamie0726私の考えでは、コントローラーが新しいオブジェクトまたはフェッチされたオブジェクトの値を設定する責任があります。このようにして、さまざまな動作でさまざまな状況でフォームを使用できます。たとえば、ユーザーがマネージャーまたはスーパーマネージャーの役​​割を持っているため、新しい色が変わる可能性があります。これはビジネスロジックであるため、フォームではなく、コントローラまたはサービス。したがって、Ceradが述べたように、私もこのソリューションを好みます。これらのデフォルト値を設定するサービスを常に作成し、コントローラーでそのサービスを使用してDRYを維持することができます。
saamorim 2013

これは私が選択したソリューションです。生成されたコントローラーには、EDITフォームとCREATEフォームを作成するための異なるメソッドがあり、それらが新しいエンティティーのデフォルト/初期データを設定する場所です。
alumi、2015年

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'エンティティでコンストラクターのパラメーターを許可するためにコールバックが使用されている場合、これは機能しないようです。
NDMは

1

ブライアンが尋ねたように:

empty_dataは、値なしで送信された場合にのみフィールドを1に設定するように見えます。値が存在しないときにフォームの入力にデフォルトで1を表示する場合はどうでしょうか?

デフォルト値を設定できます empty_value

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

0

attrにを追加することで、この問題を解決しました:

->add('projectDeliveringInDays', null, [
    'attr' => [
          'min'=>'1',
          'value'=>'1'
          ]
     ])
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.