タグ: Laravel
はじめに
Laravel 6 。ファイルを扱うシンプルな CRUD API の例を作った (今後 Dropzon.js を試すために) – oki2a24 の続きで、バリデーションとそのテストを作りました。
やりたいこと
都道府県のセレクトボックスを Select2 で作る。フォーム入力で選択肢を絞りこめるが、このとき選択肢文字列だけではなくひらがな、アルファベット (半角) でも絞り込めるようにしたい。
Select2 に渡す選択肢の配列は次を想定している。
const options = [
{ id: "1", text: "北海道", hiragana: "ほっかいどう", alphabet: "hokkaido" },
{ id: "2", text: "青森県", hiragana: "あおもりけん", alphabet: "aomoriken" },
{ id: "3", text: "岩手県", hiragana: "いわてけん", alphabet: "iwateken" },
{ id: "4", text: "宮城県", hiragana: "みやぎけん", alphabet: "miyagiken" },
{ id: "5", text: "秋田県", hiragana: "あきたけん", alphabet: "akitaken" },
];
ちなみに本投稿は Vue.js 3 で Select2 をラップして SFC (シングルファイルコンポーネント) としてコンポーネント化する例 – oki2a24 の続きにあたります。
まとめ
次のことを行えば可能と予想し、実際に実現できました。
- Select2 へ渡す Options に適当なプロパティ A, B を追加する。
- Select2 で絞り込むときにプロパティ A, B も含めて検索する。
まとめ
<php> 要素 (PHP INI 項目や定数、グローバル変数の設定) では、既存の環境変数は上書きされない。上書きしたいならば、 force 属性を使う。
ドキュメントはこちら。といいますか、 phpunit.xml で検索して最初のページでした。
Laravel7 で入力値そのものと入力値を分割した配列の両方を一度にバリデーションするためのルールの書き方 – oki2a24 を改善する話です。
ルールオブジェクトまとめ
公式ドキュメントに書いてあること
- ルールオブジェクトの使用 – カスタムバリデーションルールのメソッドを定義
php artisan make:rule <name>コマンドでapp/Rulesディレクトリに新しいルールオブジェクトのファイルを生成できる。passes($attribute, $value)メソッドでバリデーションを行う。$attribute: フォームの属性名$value: フォームに入力された属性値。これをバリデーションすることになる。
- フォームリクエストクラスの
ruleメソッでのルールオブジェクトの使用方法は、ルールを書く場所にインスタンス化すれば良い。そのため、ルールを書く際は文字列を|で区切るのではなく、配列で定義することになる。
公式ドキュメントに書いてないこと (こちらを本ページで扱う)
- クロージャの使用 – カスタムバリデーションルールのメソッドを定義 のみを使う場合、カスタムバリデーションルールが 2 つ以上になるとテスト時にどのクロージャがテストに該当するのかわからなくなる。そのため、クロージャを利用せずにルールオブジェクトのみを使うのも良いと思う。
- どうやらルールオブジェクトは 1 回のバリデーションで使ったオブジェクトをそのままエラーメッセージ出力時でも使うようだ。したがって、ルールオブジェクトクラスのコンストラクタやプロパティ (クラスのメンバ変数) を使って応用を効かせることができる。
passesメソッドで$attributeと$value以外の値を使いたい (例えばバリデーション時の判定に使う最大数とか) 場合は、ルールオブジェクトのコンストラクタで渡す。messageメソッドで例えばpassesメソッド内で出てきた値を使いたい場合は、passesメソッド内からプロパティに渡してやればよい。
ポイント
- フォーム値の事前加工 は使えない。なぜなら加工前の値もバリデーションしたいため。
- クロージャの使用 – カスタムバリデーションルールのメソッドを定義 し、その中でフォーム値を加工してバリデーションを行う。
- ただし、
rulesメソッド内に 2 つ以上のクロージャのルールが存在するとテスト時にどのクロージャがテストに該当するのかわからなくなる。そのため試してはいないが ルールオブジェクトの使用 – カスタムバリデーションルールのメソッドを定義 をした方が良いと思われる。 - 今回はクロージャの使用を押し通したため、テストではエラーメッセージを確認することでどのルールで不正となったかを確かめている。
- ただし、
- カスタムバリデーションルールのメソッド内では
'required','email:rfc,spoof'といったバリデーションルールを宣言できない。とはいえ該当するバリデーションロジックを書くのは車輪の再開発となり、おかしい。探すと、Illuminate\Validation\Concerns\ValidatesAttributesトレイトに各バリデーションルールの実装となっているのでこれをuseして利用する。
例。ユーザー削除時に連携するサービスも削除するイベント
実際に書いたコードから少し内容を変えており、実際に動かない可能性がありますことを最初にお断りします。エッセンスを伝えるためのコードとなります。
例えば、ログインに外部の OpenId Connect サービスを使う場合、今回は Google としましょうか。ユーザーを作成したときは Laravel の googles テーブルに連携時のデータを保存しているものとし、モデルでは user->google でアクセスできるものとします。
ユーザーを削除する時にイベントを実行し、リスナーで Laravel の google レコードを削除するとします。この時のリスナーの handle メソッドを、次のようにテストしました。
- ポイント。リスナーのテストのコツと言っても、リスナークラスをインスタンスかして handle メソッドを実行するだけ。アサートは実行した結果を確かめる。
- おまけポイント。 イベントリスナー DeleteGoogle クラスはコンストラクタで DI を行っている。この DI を自動的に行って欲しいので
appメソッドを使用した。 - おまけポイント。テストメソッド内でも、
appメソッドは普通に使える。 - おまけポイント。ファクトリの
statesメソッドで users レコード作成後に googles レコードも作成している。登録は、UserFactoryクラスでafterCreatingメソッドを使って行っている。
Docker イメージ php:7.4.5-apache で Apache の他に cron も動かす方法 – oki2a24 のcrond の実行ログを docker のログに出力するようにしたと思ったが出力されていない、という問題に対処できました。
ポイント
- 対象のプロセスのログを stdout や stderr へ出力しておくことが必要
- Supervisor の対象プロセスの設定で、ログを stdout や stderr へ出力するように設定
- どちらか一方ではダメで、対象プロセス自身のログと Supervisor の対象プロセスの設定の両方で stdout や stderr へ出力すること
関連したモデルの挿入、更新については公式ドキュメントに記述があります。
しかし、削除については言及されていません。
そこで、自分なりにたどり着いた最適な削除方法を残します。
フォームリクエストバリデーション – バリデーション 7.x Laravel にあるように、バリデーションロジックを含んだカスタムリクエストクラスを作成して利用することはよくあります。
しかし、フォームリクエストをどうやってユニットテストすれば良いのかについては、 Laravel ドキュメントに記載がありません。
自分自身がさまざま調べ、現在行っているユニットテストの方法を記したいと思います。
