[Symfony]DateHelperとDateValidator
2008年01月09日(水)17:00|谷口
谷口です。
今回はSymfonyのDateHelperとDateValidatorについて書きます。 DateHelperをtemplateで呼び出すには、input_date_tag関数を使います。 ただ、第3引数’rich=true’を指定するとcalendar widgetが出て日付を指定できますが、 誕生日などの入力には適していないと思います。 ‘rich=true’を指定しない場合の例を書きたいと思います。 ‘rich=true’を指定しないと、年月日のそれぞれがプルダウンメニューのインプットフォームになります。
DateHelper
例えば、下記のような感じです。
<?php
echo
input_date_tag(
ELEMENT_NAME,
DEFAULT_DATE,
array('year_start' => MIN_YEAR, 'year_end' => MAX_YEAR, 'use_month_numbers' => 'true'));
?>
ここで、各引数の説明をします。
- 第1引数:HTMLのname属性です(フォームから送信されるデータの名前になります)。
- 第2引数:初期日付
- 第3引数:オプション
上記サンプルで指定しているオプションは最小年と最大年、月の表示に数字を用いるという設定となります。 最小年・最大年を指定しないと、年の選択範囲が初期日付の5年前~5年後となります。 フォームを送信すると、ELEMENT_NAME[year],ELEMENT_NAME[month],ELEMENT_NAME[day]として送信されます。 ただ、残念ながら、sfDateValidatorはこの形の送信に対して機能しません・・・。 そこで、sfDateValidatorを継承したValidatorクラスを作成します。
DateValidator
上でも記したように、sfDateValidatorはそのままではELEMENT_NAME[year],ELEMENT_NAME[month],ELEMENT_NAME[day]のパラメータを処理できません。下記のようなValidatorを作ってみました。 executeではymlで設定した値を受け取って、指定最大日付と最小日付の間になければ、falseを返します。 また、getValidDateメソッドはstrtotime()関数を使っており、約1902年~2038年は判定できます。 2038年以降または1902年以前を判定したい場合は、独自でメソッドを用意する必要がありますが、 この値をDBに登録する場合、型がDate型でORマッパにPropelを使用している場合、Propelが例外を出しますので注意が必要です。
<?php
class myDateValidator extends sfDateValidator
{
public function initialize( $context, $parameters = null )
{
parent::initialize($context);
$this->getParameterHolder()->add($parameters);
return true;
}
public function execute( &$value, &$error )
{
$params = $this->getParameterHolder()->getAll();
$culture = $this->getContext()->getUser()->getCulture();
$input_date = $this->getValidDate(join('-', $value), $culture);
$min_date = $this->getValidDate($params['min'], $culture);
$max_date = $this->getValidDate($params['max'], $culture);
if(empty($input_date)){
$error = $params['error_message'];
return false;
}
if($min_date <= $input_date && $input_date <= $max_date){
return true;
} else {
$error = $params['error_message'];
return false;
}
}
}
?>
validate用のymlは次のような感じです。
ELEMENT_NAME:
required: false
validators: v_mydate
v_mydate:
class: myDateValidator
param:
min: "1902-01-01"
max: "2000-12-31"
error_message: "1902年1月1日~2000年12月31日の正しい日付を入力してください"
おわりに
calendar widgetを使えば、こんな面倒なことはしなくても良いのですが、想定される入力値の幅が広いと使い勝手が悪く感じますので、 作ってみました。