Zend

【Zend】zend validateで、いずれか1つを必須にする方法

どうも、katです。

突然ですが、zend validateで、こんなこと思ったりしませんか?

・複数の入力項目のうち、どれか一つだけを必須にしたい
 ※逆に言うと、複数項目の全てが空だったときだけエラーにしたい。

そんなとき、ググっても中々答えが見つからない~!

てことありますよね。

今回は、上記の問題を簡単に解決する方法について書いていこうと思います。

準備

ここでは、ユーザーの検索画面を例にして進めていきます。

例えば、検索項目に、「名前」「生年月日(From)」「生年月日(To)」という項目があるとします。

・example.html

ユーザー名:<input name="user_name" type="text" value="">
生年月日(From):<input name="birth_day_from" type="text" value="">
生年月日(To):<input name="birth_day_to" type="text" value="">

バリデーション実装

必須のバリデーションのみの場合

それでは、実際にバリデーションを実装します。

まずは、「ユーザー名」に、「いずれかの項目が必須」以外のバリデーションが無い場合で説明していきます。(他のバリデーションがある場合は次項で説明しています。)

早速ですが、実装内容は下記のようになります。

・example.php

'user_name' => [
  'continue_if_empty' => true, // ← 重要!!
  'required' => true,
  'validators' => [
    [
      'name' => 'callback',
      'options' => [
        'messages' => [
          'callbackValue' => "ユーザー名、生年月日のいずれかは必須です。",
        ],
        'callback' => function($value, $context = array()) {
          $userName = $value;
          $birthDayFrom = $context['birth_day_from'];
          $birthDayTo = $context['birth_day_to'];

          // 全て未入力の場合のみfalseを返す
          return ($userName || $birthDayFrom || $birthDayTo );
        },
      ],
    ]
  ],
],
'birth_day_from' => [
  ・・・
],
'birth_day_to' => [
  ・・・
],

ここで重要となるのが、

  'continue_if_empty' => true,
  'required' => true,

を指定することです。

通常、’required’がtrueの場合に空の値が渡ってくると、他のバリデーションチェックを行わずに必須チェックエラーのみ発生させて終了しますが、’continue_if_empty’をtrueにすることで、空の場合でも他のバリデーションのチェックまで行ってくるれるようになります。

後はcallback関数に、行いたいバリデーションの内容を記載するだけです。(falseをreturnした場合にエラーが発生します。)

ただし、この場合「ユーザー名」に他のバリデーションを追加すると、空の場合でも全てのバリデーションが動いてしまいます。

その場合の対処法は、次項で説明します。

他のバリデーションと組み合わせたい場合

今度は、「ユーザー名」に、「25文字まで」等、他のバリデーションがある場合で説明します。

他のバリデーションがない場合だと前項で問題ありませんが、他のバリデーションがある場合はこちらの書き方にする必要があります。

まず、適当なhiddenのinputタグを追加します。

・example.html

ユーザー名:<input name="user_name" type="text" value="">
生年月日(From):<input name="birth_day_from" type="text" value="">
生年月日(To):<input name="birth_day_to" type="text" value="">
<!-- 下記の行を追加 -->
<input name="required_field" type="hidden" value="">

次に、バリデーションを修正します。

・example.php

'user_name' => [ // これはユーザー名の別のバリデーションです。
  'validators' => [
    [
      'name' => 'stringLength',
      'options' => [
        'max' => 25,
        'messages' => [
          'stringLengthTooLong' => 'ユーザー名は25文字以下で入力してください'
        ]
      ]
    ]
  ]
],
'birth_day_from' => [
  ・・・
],
'birth_day_to' => [
  ・・・
],
'required_field' => [ // これが「いずれか必須」のバリデーションです。
  'continue_if_empty' => true,
  'required' => true,
  'validators' => [
    [
      'name' => 'callback',
      'options' => [
        'messages' => [
          'callbackValue' => "ユーザー名、生年月日のいずれかは必須です。",
        ],
        'callback' => function($value, $context = array()) {
          $userName = $context['user_name'];
          $birthDayFrom = $context['birth_day_from'];
          $birthDayTo = $context['birth_day_to'];

          // 全て未入力の場合のみfalseを返す
          return ($userName || $birthDayFrom || $birthDayTo );
        },
      ],
    ]
  ],
],

となります。

変わったのは、’user_name’ではなく、‘required_field’の配列に「いずれかの項目が必須」のバリデーションを入れたことです。

これにより、他の項目の影響を受けずに、バリデーションのチェックが行えます。

最後に

いかがでしたでしょうか?

標準にありそうでないバリデーションですね。

もし他にもっといい方法ある!などありましたら、コメントしていただけるとありがたいです。

以上、zend validateで「いずれか一つを必須にする」のバリデーションの書き方でした~。

ABOUT ME
kat
プログラマー歴7年、2歳の子供を持つパパです。 興味のあることはプログラミングや今後のIT技術などです。 趣味でオンラインカードゲームのサイトを運営しております。 プログラミングを通して社会に貢献していきたいです。