メインメニュー
XAMPP アレンジ
IED
WSL2
-
道具箱
リポジトリ編
フレームワーク編
公開ソフトウェア
メタ
リンク
- PHP ライブラリ
- PHP 言語
apricot:app:validation目次
Apricot バリデーション
— y2sunlight 2020-05-14
関連記事
- Apricot アプリ
- Apricot バリデーション
ユーザ登録画面にバリデーションの機能を追加します。
バリデーター
Apricotでは Valitron を使いサーバ側のバリデーションで使用します。以下では、Valitron の設定方法について述べます。詳細は Valitron の README をご覧下さい。
言語ファイル
Valitronの言語ファイルを以下の手順でカスタマイズします。
vendor/vlucas/valitron/lang/Valitron/ja.php
を以下にコピーしますassets/lang/ja/vlucas.valitron.php
コピーしたvlucas.valitron.php
を以下のように変更します。/apricot/assets/lang/ja
- vlucas.valitron.php
<?php return array( 'required' => "を入力してください", 'equals' => "は「%s」と同じ内容を入力してください", 'different' => "は「%s」と異なる内容を入力してください", 'accepted' => "に同意してください", 'numeric' => "は数値を入力してください", 'integer' => "は半角数字で入力してください", 'length' => "は%d文字で入力してください", 'min' => "には%sより大きな値を入力してください", 'max' => "には%sより小さな値を入力してください", 'listContains' => "には選択できない値が含まれています", 'in' => "には選択できない値が含まれています", 'notIn' => "には選択できない値が含まれています", 'ip' => "はIPアドレスの書式として正しくありません", 'email' => "の書式が正しくありません", /* 修正 */ 'url' => "はURLの書式として正しくありません", 'urlActive' => "はアクティブなドメインではありません", 'alpha' => "は半角英字で入力してください", 'alphaNum' => "は半角英数字で入力してください", 'slug' => "は半角英数字、もしくは「-」「_」の文字で入力してください", 'regex' => "の書式が正しくありません", 'date' => "の書式が正しくありません", /* 修正 */ 'dateFormat' => "は「%s」の書式で日付を入力してください", 'dateBefore' => "は「%s」以前の日付を入力してください", 'dateAfter' => "は「%s」以後の日付を入力してください", 'contains' => "は「%s」を含んでいなければいけません", 'boolean' => "は真偽値である必要があります", 'lengthBetween' => "は%d〜%d文字で入力してください", 'creditCard' => "はクレジットカード番号の書式として正しくありません", 'lengthMin' => "は%d文字以上入力してください", 'lengthMax' => "は%d文字以内で入力してください", 'instanceOf' => "は「%s」のインスタンスではありません", 'ascii' => "は半角文字で入力して下さい", /* 追加 */ 'unique' => "は既に使用されています", /* 追加 */ );
'email
' と'date
' のテキストを変更します'ascii
' と'unique
' のテキストを追加します
設定ファイル
以下の設定ファイルを所定の場所( /apricot/config/setting )に作成して下さい。
/apricot/config/setting
- validator.setting.php
<?php return [ 'lang_dir' => assets_dir('lang/'.env('APP_LANG')), 'lang' => 'vlucas.valitron', ];
- lang_dir — 言語ファイルの保存フォルダ(既定値は
/apricot/assets/lang/ja
) - lang — 言語ファイル名( 拡張子を除いたベース名を指定 )
初期設定ファイル
以下の初期設定ファイルを所定の場所( /apricot/config/setup )に作成して下さい。
/apricot/config/setup
- validator.setup.php
<?php //------------------------------------------------------------------- // Valitron\Validatorの初期設定 //------------------------------------------------------------------- return function():bool { \Valitron\Validator::langDir(config('validator.lang_dir')); \Valitron\Validator::lang(config('validator.lang')); //------------------------------------------------------------------- // カスタムルールの追加 //------------------------------------------------------------------- /* * uniqueルール: ユニーク属性の検査を行う * [例] rule('unique','ユニークカラム名','テーブル名','IDカラム名') */ Valitron\Validator::addRule('unique', function($field, $value, array $params, array $fields) { if (count($params)<1) return false; $query = ORM::for_table($params[0])->where($field, $value); if ((count($params)>1) && array_key_exists($params[1], $fields)) { $id_field = $params[1]; $query = $query->where_not_equal($id_field, $fields[$id_field]); } $users = $query->find_one(); return ($users===false); }, 'is not unique'); return true; // Must return true on success };
初期設定ファイルでは以下の事をおこないます:
- 言語ファイルの指定
- カスタムルール(uniqueルール)の追加
uniqueルール
uniqueルールはデーターベースのユニーク制約の為のルールです。
使用法: rule('unique',$unique_column_name, $table_name, $id_column_name)
- $unique_column_name — ユニークカラム名
- $table_name — テーブル名
- $id_column_name — IDカラム名
// 使用例 $validator = new \Valitron\Validator($inputs); $validator->rule('unique','account', 'user', 'id');
アプリケーション設定の変更
上で作った validator.setup.php をアプリケーションの設定ファイル(app.php)に追加します。
/apricot/config
- app.php
<?php return [ 'setup' =>[ config_dir('setup/whoops.setup.php'), /* Error handler(whoops) */ config_dir('setup/bladeone.setup.php'), /* View template (BladeOne) */ config_dir('setup/aliases.setup.php'), /* Class aliases for view template and so on */ config_dir('setup/idiorm.setup.php'), /* ORM(idiorm) */ config_dir('setup/validator.setup.php'), /* Valitron\Validator */ ], 'middleware' =>[], 'auth' =>[], 'csrf' =>[], ];
エラーバッグ
ValidatorErrorBagクラス
コアの ErrorBagクラス を継承してバリデーション用のエラーバッグ( ValidatorErrorBag )を作ります。
/apricot/app/Foundation
- ValidatorErrorBag.php
<?php namespace App\Foundation; use Core\Foundation\ErrorBag; class ValidatorErrorBag extends ErrorBag { public const BAG_KEY = 'validator'; /** * Create Validator Error Bag * @param array $errors \Valitron\Validator Errors */ public function __construct($validator_errors) { $errors = []; foreach($validator_errors as $key=>$value) { $errors[$key] = $value[0]; } parent::__construct($errors, self::BAG_KEY); } }
'validator
' と言う名前でエラーバッグを生成します。- 使用できるメソッドなど、機能的にはErrorBagクラスと全く同じです。
クラスエイリアス
ValidatorErrorBagクラスをクラスエイリアスに追加します。
/apricot/config/setup
- aliases.setup.php
<?php //------------------------------------------------------------------- // ビューテンプレートで使うクラスエイリアスを登録 //------------------------------------------------------------------- return function():bool { $aliases = [ /* Core */ ... /* App */ 'ViewHelper' => \App\Helpers\ViewHelper::class, 'ValidatorErrorBag' => \App\Foundation\ValidatorErrorBag::class, ]; ... return true; // Must return true on success };
- ViewHelper の下に ValidatorErrorBag のエイリアスを追加します。
インターセプター
Apricotではバリデーションをインターセプターの中に実装します。以下にインターセプターの作成方法について説明します。
インターセプター
とはアクションの前処理の事で、ミドルウェアに似ていますが後処理はなく、各コントローラで独自に設定することができます。主な用途としては入力データの検証や変換です。本章では、インターセプターを直接アクションから呼び出していますが、後述の「Apricot 拡張: インターセプター」では、アクションをインターセプターに依存しない形で再実装します。
フォルダの作成
Controllers の下に Interceptorsフォルダ を作って下さい。
apricot [プロジェクト] | ├── app [アプリ] | | | ├── Controllers [コントローラ] | | | | | ├── Interceptors [インターセプター]
ユーザインターセプター
インターセプターメソッドのシグネチャには次の規則があります:
- interceptorMethod( Controller $controller, [, mixed $… ] ):mixed
- $controller — インターセプターを呼び出したコントローラ
- $… — インターセプターを呼び出したアクションメソッドと同じ引数
- 戻り値
- 成功の場合 — void を返す
- 失敗の場合 — Responseオブジェクトを返す
以下にユーザインターセプター( UserInterceptor )を示します。
/apricot/app/Controllers/Interceptors
- UserInterceptor.php
<?php namespace App\Controllers\Interceptors; use Core\Input; use App\Foundation\Controller; use App\Foundation\ValidatorErrorBag; /** * ユーザインターセプタ― */ class UserInterceptor { /** * ユーザレコード挿入 * @return void|\Core\Foundation\Response return Response if failed */ public function insert(Controller $controller) { $inputs = Input::all(); // Validation $v =(new \Valitron\Validator($inputs)) ->rule('required', ['account','password']) ->rule('alphaNum','account') ->rule('unique','account','user','id') ->rule('ascii','password') ->rule('equals','password','password_confirmation') ->rule('email', 'email') ->labels(inputLabels('messages.user.create')); if(!$v->validate()) { $errorBag = new ValidatorErrorBag($v->errors()); return redirect(back())->withInputs()->withErrors($errorBag); } // Remove unnecessary inputs Input::remove('password_confirmation'); } /** * ユーザレコード更新 * @param int $id * @return void|\Core\Foundation\Response return Response if failed */ public function update(Controller $controller, int $id) { $inputs = Input::all(); // Validation $v =(new \Valitron\Validator($inputs)) ->rule('ascii','password') ->rule('equals','password','password_confirmation') ->rule('email', 'email') ->labels(inputLabels('messages.user.create')); if(!$v->validate()) { $errorBag = new ValidatorErrorBag($v->errors()); return redirect(back())->withInputs()->withErrors($errorBag); } // Remove unnecessary inputs Input::remove('password_confirmation'); } }
バリデーションの手順は以下の通りです。
- Input::all()でフォームデータを取得します
- Validatorの生成
- rule()メソッドで検証ルールを適用します
- labels()メソッドでエラーメッセージで使う項目名を設定します
Validatorのvalidate()メソッドで検証します- 検証エラーの時
- withInputs()で入力変数をフラッシュ変数に保存します
- withErrors()でバリデーションのエラーバッグをフラッシュ変数に保存します
- redirect()で前画面にリダイレクトするResponseオブジェクトをします
検証成功の時- 不要になったバリデーション用のフォームデータを削除します
検証ルール
- insert() : レコード挿入時
required
— 必須入力(account, password)alphaNum
— 半角英数入力(account)unique
— ユニーク制約(account)ascii
— 半角入力(password)equals
— 確認入力(password = password_confirmation)email
— メールアドレス(email)
- update() : レコード更新時
ascii
— 半角入力(password)equals
— 確認入力(password = password_confirmation)email
— メールアドレス(email)
ユーザコントローラ
以下の手順に従い、ユーザコントローラ( UserController )の
insert()
とupdate()
にバリデーション処理を追加します。- インターセプター( UserInterceptor )を生成します
- アクションメソッドと同名のインターセプターメソッドを呼び出します
- 戻り値がResponseオブジェクトの場合はバリデーションエラーです
- Responseオブジェクトを返してアクションを終了します
戻り値がvoidの場合は正常終了です/apricot/app/Controllers
- UserController.php
<?php namespace App\Controllers; use App\Exceptions\ApplicationException; use App\Foundation\Controller; use App\Models\User; use Core\Input; /** * ユーザコントローラ */ class UserController extends Controller { ... /** * ユーザレコード挿入 * @return \Core\Foundation\Response */ public function insert() { // バリデーション $response = (new Interceptors\UserInterceptor())->insert($this); if ($response instanceof \Core\Foundation\Response) { return $response; } $inputs = Input::all(); try { // ユーザレコード挿入 $user = $this->user->insert($inputs); } catch(\Exception $e) { throw new ApplicationException(__('messages.error.db.insert'),$e->getMessage(),0,$e); } // ユーザ一編集画面にリダイレクト return redirect(route("user/{$user->id}/edit"))->with('msg',__('messages.success.db.insert')); } ... /** * ユーザレコード更新 * @param int $id * @return \Core\Foundation\Response */ public function update(int $id) { // バリデーション $response = (new Interceptors\UserInterceptor())->update($this, $id); if ($response instanceof \Core\Foundation\Response) { return $response; } $inputs = Input::all(); try { // レコード更新 $this->user->update($id, $inputs); } catch(ApplicationException $e) { throw $e; } catch(\Exception $e) { throw new ApplicationException(__('messages.error.db.update'),$e->getMessage(),0,$e); } // ユーザ一編集画面にリダイレクト return redirect(route("user/{$id}/edit"))->with('msg',__('messages.success.db.update')); } ... }
HTMLテンプレート
HTMLテンプレートを以下に示すように変更して下さい。
新規登録用のテンプレート
/apricot/assets/views/user
- create.blade.php
.... {{-- password --}} <div class="form-group row"> <label for="password" class="col-md-2 col-form-label">{{__('messages.user.create.password')}}</label> <div class="col-md-10"> <input type="password" name="password" id="password" class="form-control" value="{{old('password')}}" placeholder="{{__('messages.user.create.hint_password')}}"> </div> </div> {{-- password_confirmation --}} <div class="form-group row"> <label for="password_confirmation" class="col-md-2 col-form-label">{{__('messages.user.create.password_confirmation')}}</label> <div class="col-md-10"> <input type="password" name="password_confirmation" id="password_confirmation" class="form-control" value="{{old('password_confirmation')}}" placeholder="{{__('messages.user.create.hint_password_confirmation')}}"> </div> </div> ....
{{-- password --}}
の部分を差し替えます- input-typeをpasswordに変更
{{-- password_confirmation --}}
の部分を追加します- 確認入力用に追加
編集用のテンプレート
/apricot/assets/views/user
- edit.blade.php
.... {{-- password --}} <div class="form-group row"> <label for="password" class="col-md-2 col-form-label">{{__('messages.user.edit.password')}}</label> <div class="col-md-10"> <input type="password" name="password" id="password" class="form-control" value="{{old('password')}}" placeholder="{{__('messages.user.edit.hint_password')}}"> </div> </div> {{-- password_confirmation --}} <div class="form-group row"> <label for="password_confirmation" class="col-md-2 col-form-label">{{__('messages.user.edit.password_confirmation')}}</label> <div class="col-md-10"> <input type="password" name="password_confirmation" id="password_confirmation" class="form-control" value="{{old('password_confirmation')}}" placeholder="{{__('messages.user.edit.hint_password_confirmation')}}"> </div> </div> ....
{{-- password --}}
の部分を差し替えます- input-typeをpasswordに変更
{{-- password_confirmation --}}
の部分を追加します- 確認入力用に追加
テスト実行
バリデーションを使ってみましょう。ユーザ一覧画面を表示します。
■ [新規]ボタンを押して下さい。
■ 全て未入力の状態で、[保存]ボタンを押すとバリデーションが働き以下の画面が出ます。
■ アカウントとパスワードの必須入力エラーエラーメッセージが表示されます。
様々なバリデーション
ユーザ新規登録画面では以下の様々なバリデーション機能があります。試してみて下さい。
- required — 必須入力(account, password)
- alphaNum — 半角英数入力(account)
- unique — ユニーク制約(account)
- ascii — 半角入力(password)
- equals — 確認入力(password = password_confirmation)
- email — メールアドレス(email)
apricot/app/validation.txt · 最終更新: 2020/06/03 14:37 by tanaka
コメント