読者です 読者をやめる 読者になる 読者になる

Symfony2のDateTypeのバグ対策

※追記 (2012/02/29 20:40)
というかそもそも、下記を実装した後に気づいたんですが、date_patternをオーバーライドするフォームテーマなんて作成しないでも直接オーバーライド出来るんじゃないか?と思って試してみたら出来ました。

特にテンプレートとか作らずに下記のように指定すれば出来ます。

{{ form_widget(form.sample_date, { 'date_pattern': '{{ year }}年{{ month }}月{{ day }}日' }) }}


id:shimookaさんのブログでDateTypeにバグがあるという記事があがっていたので試してみました。

実際にテストコードを書いて確認してみると確かにformatにyyyy年MM月dd日を指定しているのに無視される。

id:shimookaさんの記事には対応策が載っているが、Symfony2のコアコードを変更するのはあまりスマートではないので、フォームテーマを作成して対策してみました。

デフォルトのフォームテーマを確認すると、下記のようになってます。

vendor/symfony/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig

{% block date_widget %}
{% spaceless %}
    {% if widget == 'single_text' %}
        {{ block('field_widget') }}
    {% else %}
        <div {{ block('widget_container_attributes') }}>
            {{ date_pattern|replace({
                '{{ year }}':  form_widget(form.year),
                '{{ month }}': form_widget(form.month),
                '{{ day }}':   form_widget(form.day),
            })|raw }}
        </div>
    {% endif %}
{% endspaceless %}
{% endblock date_widget %}

date_patternという変数には{{ year }}-{{ month }}-{{ day }}という文字列が入っています。
なので、ここを独自のフォームテーマを作成して、オーバーライドしてあげればSymfony2のコアコードを変えずに実装できます。

まずは下記のようにデフォルトのフォームテーマを元にdate_widgetのみ拡張するフォームテーマを作成します。

src/My/Bundle/DemoBundle/Resources/views/Form/form_layout.html.twig

{% extends "form_div_layout.html.twig" %}

{% block date_widget %}
{% spaceless %}
    {# _date_patternが定義されていれば、date_patternをオーバーライド #}
    {% if _date_pattern is defined %}
        {% set date_pattern = _date_pattern %}
    {% endif %}

    {% if widget == 'single_text' %}
        {{ block('field_widget') }}
    {% else %}
        <div {{ block('widget_container_attributes') }}>
            {{ date_pattern|replace({
                '{{ year }}':  form_widget(form.year),
                '{{ month }}': form_widget(form.month),
                '{{ day }}':   form_widget(form.day),
            })|raw }}
        </div>
    {% endif %}
{% endspaceless %}
{% endblock date_widget %}

_date_patternが定義されていればdate_patternをオーバーライドするという処理をdate_widgetブロックの直下に追加しました。


後は実際のフォームを利用するテンプレートで下記のようにしてフォームを呼び出すと独自の形式でフォームが呼び出せるようになります。

{% form_theme form "MyDemoBundle:Form:form_layout.html.twig" %}

{{ form_widget(form.sample_date, { '_date_pattern': '{{ year }}年{{ month }}月{{ day }}日' }) }}