ブログ

[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を使えば、こんな面倒なことはしなくても良いのですが、想定される入力値の幅が広いと使い勝手が悪く感じますので、 作ってみました。

この記事に関するお問い合わせはこちら

ページの先頭へ