バリデーションを記載していると、orのバリデーションが欲しくなる時がたまにある。
だがLaravelにOrのバリデーションが存在しない。
正規表現で対応できることも多いが、今回は既存バリデーションをそのまま使用したかったのでor判定する新しいバリデーションを作成してみた
ORバリデーション
メッセージはもうちょっと改良の余地あり。
エラーになったバリデーションメッセージを連結するほうがいいかも。
OrRule.php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\Validator;
class OrRules implements Rule
{
private $rules = [];
function __construct(Array $rules)
{
$this->rules = $rules;
}
/**
* バリデーションの成功を判定
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
foreach ($this->rules as $rule) {
$validator = Validator::make([$attribute => $value], [
$attribute => $rule
]);
if (!$validator->fails()) {
// エラーなしなら終了
return true;
}
}
return false;
}
/**
* バリデーションエラーメッセージの取得
*
* @return string
*/
public function message()
{
return ':attribute は正しい形で入力してください';
}
}
使い方
// 画像ファイルまたはURLまたはbooleanなら通す ルール定義
[
'image' => [new OrRules(['mimes:jpeg,bmp,png', 'url', 'boolean'])]
]
開発経緯
開発経緯を少しだけ。
ちょっと仕事で複数画像を順番を保持しつつ登録処理を書かなければならないことがあった。
登録するときはすべて新規登録のため、画像のルールもmimesだけで問題なかったが・・・
問題は更新するときだった
画像の更新対象がわからない問題
更新するときは以下の3つの状態をLaravel側で認識しないといけなかったため、単純にmimesだけ通すルールだと判断ができなかった。
- 「どの画像が更新されたか」
- これはmimesで問題ない
- input に画像がセットされるため
- これはmimesで問題ない
- 「どの画像が更新されていないか」
- これはどうやって?
- 「どの画像が削除されたか」
- これはどうやって?
色々考えた結果、以下の考えのもと処理を作成。
- 「どの画像が更新されたか」
- これはmimesで問題ない
- input に画像をセット
- これはmimesで問題ない
- 「どの画像が更新されていないか」
-
登録画像パスのままなら更新されていない
- input に登録画像URLをセット
-
登録画像パスのままなら更新されていない
- 「どの画像が削除されたか」
-
falseなら削除されている
- 画像の設定が削除されたらinput にfalseをセット
-
falseなら削除されている
このため、「mimesまたはurlまたはboolean」のバリデーションルールが必要になり、
上記に示したORバリデーションを作成することになった。
正直、このやり方がベストなのかどうかまではわからん。。。