のような年月のみを選択する場合向け。
DateTime
オブジェクトとマッピングする前提。

どうやるのが正解かはわからないけど、 DateType
をそのまま使うと苦しいのでとりあえず雑に作って動いた拡張 FormType を載せておきます。
<?php
namespace Fivestar\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\ReversedTransformer;
use Symfony\Component\OptionsResolver\OptionsResolver;
class YearMonthType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function getParent()
{
return DateType::class;
}
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
if ($options['widget'] === 'choice') {
$builder
->resetViewTransformers()
->addViewTransformer(new DateTimeToArrayTransformer(
$options['model_timezone'], $options['view_timezone'], array('year', 'month')
))
;
}
if ($options['input'] === 'array') {
$builder
->resetModelTransformers()
->addModelTransformer(new ReversedTransformer(
new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], array('year', 'month'))
))
;
}
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'widget' => 'choice',
]);
}
/**
* {@inheritdoc}
*/
public function finishView(FormView $view, FormInterface $form, array $options)
{
if ($options['widget'] === 'choice') {
$view['day']->vars['attr']['style'] = 'display:none;';
}
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'year_month';
}
}
DateType
をベースにプルダウン形式を使う前提として、 day
を style="display:none;"
で消すという雑な対応で。フィールドの存在ごと消したいけどおそらく無理っぽい。
ポイントは Transformer 系を一度リセットして再設定してるところ。DateTime
オブジェクトで年月のみを扱う場合、内部的には日や時分秒も補完され、1度オブジェクトを経由すると day
は null
ではなく 1
扱いになるため、 Transformer の第3引数にて year
と month
のみを参照するようにしておくと平和です。
$ php -r "var_dump((new DateTime('2015-12'))->format('Y-m-d H:i:s'));"
string(19) "2015-12-01 00:00:00"
入力必須要素なら finishView
あたりで適当な value
値を day
にぶっこんどきゃいいんだけど、入力が任意の場合は空のままサブミットすると (null)-(null)-01
とかなって死ぬし、検索してると入力必須の場合しか考慮してなさそうなコードも結構多かったので、諸々考慮されたやつが標準なりで入ってるといいなと思いました。僕はしません。
表示結果
$builder->add('yearMonth', YearMonthType::class);
とりあえずそのまま出した場合:

{{ form_row(form.yearMonth) }}
クレカの有効年月用:

{{ form_row(form.yearMonth, {
'date_pattern': '{{ month }}/{{ year }}',
}) }}