このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン 前のリビジョン 次のリビジョン | 前のリビジョン 次のリビジョン 両方とも次のリビジョン | ||
apricot:usage:ja:controller [2020/08/26 17:39] y2sunlight [インターセプターの登録] |
apricot:usage:ja:controller [2020/08/26 21:23] y2sunlight |
||
---|---|---|---|
行 1: | 行 1: | ||
- | > 編集中 | ||
- | |||
- | ---- | ||
- | |||
====== Apricot コントローラ ====== | ====== Apricot コントローラ ====== | ||
--- // | --- // | ||
行 94: | 行 90: | ||
===== コントローラとアクション ===== | ===== コントローラとアクション ===== | ||
- | ルーティングによって設定されているエンドポイント(URI)がアクセスされると、Apricotはハンドラー(クロージャでない場合)で指定されている '' | + | ルーティングによって設定されているエンドポイント(URI)がアクセスされると、Apricotはハンドラー(クロージャでない場合)で指定されている '' |
+ | |||
+ | < | ||
+ | / | ||
+ | </ | ||
以下は、Apricotのスケルトンに含まれているHomeコントローラです。このコントローラにはindexアクションだけが含まれています。 | 以下は、Apricotのスケルトンに含まれているHomeコントローラです。このコントローラにはindexアクションだけが含まれています。 | ||
行 173: | 行 173: | ||
=== インターセプターの登録 === | === インターセプターの登録 === | ||
- | < | + | < |
$this-> | $this-> | ||
$this-> | $this-> | ||
行 182: | 行 182: | ||
=== トランザクションの適用 === | === トランザクションの適用 === | ||
- | < | + | < |
$this-> | $this-> | ||
</ | </ | ||
行 230: | 行 230: | ||
上図から分かるようにミドルウェアパイプラインから見ると、インターセプターはアクションに含まれます。ミドルウェアとの一番の違いは、ミドルウェアは基本的に全てのコントローラを対象としているのに対し、インターセプターは、各コントローラで独自に設定ができるという点です。 | 上図から分かるようにミドルウェアパイプラインから見ると、インターセプターはアクションに含まれます。ミドルウェアとの一番の違いは、ミドルウェアは基本的に全てのコントローラを対象としているのに対し、インターセプターは、各コントローラで独自に設定ができるという点です。 | ||
- | インターセプターの主な用途としては入力データの検証(バリデーション)、入力データのフィルタリングや変換です。インターセプターを作ることで、すっきりしたアクションを作ることができます。 | + | インターセプターの主な用途としては以下のものがあります: |
+ | |||
+ | * 入力データの検証(バリデーション) | ||
+ | * 不要な入力データの除去 | ||
+ | * 入力データの変換 | ||
+ | |||
+ | インターセプターを利用することで、簡潔なアクションを作ることができます。 | ||
+ | |||
+ | \\ | ||
==== インターセプターの登録 ==== | ==== インターセプターの登録 ==== | ||
行 276: | 行 284: | ||
==== インターセプターの作成 ==== | ==== インターセプターの作成 ==== | ||
- | Apricotでは、インターセプターを配置する場所は以下に決めれられいます。 | + | インターセプターは以下の場所に配置する必要があります( 名前空間は '' |
< | < | ||
/ | / | ||
</ | </ | ||
- | |||
- | 結果として、インターセプタークラスの名前空間は '' | ||
インターセプターメソッドのシグネチャには次の規則があります: | インターセプターメソッドのシグネチャには次の規則があります: | ||
- | | + | <code php> |
- | - $controller | + | /** |
- | | + | * Interceptor method |
- | * 戻り値 | + | * |
- | - 成功の場合 --- void を返す | + | * @param Controller |
- | - 失敗の場合 | + | * @param mixed $... 対応するアクションメソッドと同じ引数 |
+ | | ||
+ | */ | ||
+ | public function interceptorMethod( Controller $controller, | ||
+ | </ | ||
以下にユーザコントローラのinsertアクションに対するインターセプター( UserInterceptor@insert )の例を示します。 | 以下にユーザコントローラのinsertアクションに対するインターセプター( UserInterceptor@insert )の例を示します。 | ||
行 320: | 行 331: | ||
$v =(new \Valitron\Validator($inputs)); | $v =(new \Valitron\Validator($inputs)); | ||
-> | -> | ||
+ | -> | ||
-> | -> | ||
行 334: | 行 346: | ||
</ | </ | ||
- | > TODO: | + | この例では、Input::all() で入力変数を取得した後に、'' |
- | この例では、Input::all() で入力変数を取得した後に、この変数を使用して | + | バリデーションが失敗した時、withInputs() で入力変数を、withErrors() で[[apricot: |
- | Validatorの rule() メソッドは入力変数に検証ルールを適用します。この例では、必須入力を意味するrequired ルールを入力変数の account と password に適用しています。また、labels() メソッドはエラーメッセージで使う項目名を設定しています。 | + | バリデーションが成功した時、不要になった入力変数 |
- | + | ||
- | バリデーションの実行は validate() メソッドで行います。バリデーションが失敗した時、withInputs() で入力変数を、withErrors() でバリデーションのエラーバッグをフラッシュ変数に保存します。そして、redirect()で前画面にリダイレクトするレスポンスオブジェクトを生成し、それを返します。Apricotは、インターセプターがレスポンスオブジェクトを返した時、コントローラーアクションを呼び出さずに、そのレスポンスをクライアントに返します。 | + | |
- | + | ||
- | バリデーションの詳細は Valitron の README をご覧下さい。 | + | |
\\ | \\ | ||
行 348: | 行 356: | ||
===== トランザクション ===== | ===== トランザクション ===== | ||
- | ユーザ登録画面にトランザクションの機能を追加します。トランザクションを作るか否かはアクション毎に設定できるようにします。また、トランザクション機能を追加することによりアクションでスローされる ApplicationException | + | Apricotでは、コントローラのアクションをラップする形で、アクションにトランザクションを適用することができます。Apricotは、トランザクションの適用されたアクションを呼び出す前にトランザクションを開始し、アクションが正常に終了するとそのトランザクションをコミットします。アクションが '' |
- | * 楽観的ロック例外(OptimissticLockException) | + | \\ |
- | * 対象レコードが存在しない(レコード更新時および削除時) | + | |
- | * その他のアクションで発生する'' | + | |
- | 通常、トランザクションは更新系の処理で設定するするので、参照系で発生した全ての例外は集約エラーハンドラで処理されエラー画面が表示されます。この状況を避けたい場合は、次の何れかの選択になるでしょう。 | + | ==== トランザクションの適用 ==== |
- | * 参照系アクションもトランザクションを設定する | + | アクションにトランザクションを適用するには、以下のように、コンストラクターの中で、コントローラの '' |
- | * アクション内のcatchブロックでエラーメッセージ付きの入力画面をレンダリングする | + | |
- | \\ | + | <code php> |
+ | class FooController extends Controller | ||
+ | { | ||
+ | public function __construct(User $user) | ||
+ | { | ||
+ | // トランザクションの適用 | ||
+ | $this-> | ||
+ | ... | ||
+ | } | ||
+ | .... | ||
+ | } | ||
+ | </ | ||
- | ==== 使用例:ユーザコントローラ ==== | + | この例では、insert、updateそしてdeteleの各アクションにトランザクションを適用しています。このように、'' |
- | アクションのトランザクション処理を有効にしたい場合は、コントローラのコンストラクタの中でControllerクラスのtransactional()メソッドを使って、以下のようにします。 | + | \\ |
- | * **transactional( ' | + | ==== トランザクション処理 ==== |
- | {{fa> | + | 以下は、ユーザコントローラの update アクションの例です。 |
- | <code php UserController.php> | + | |
- | <?php | + | |
- | namespace App\Controllers; | + | |
- | + | ||
- | use App\Exceptions\ApplicationException; | + | |
- | use App\Foundation\Controller; | + | |
- | use App\Models\User; | + | |
- | use Core\Input; | + | |
+ | <code php> | ||
/** | /** | ||
- | | + | |
+ | * | ||
+ | * @param int $id | ||
+ | * @return \Apricot\Foundation\Response | ||
*/ | */ | ||
- | class UserController extends Controller | + | public function update(int $id) |
{ | { | ||
- | | + | |
- | | + | |
- | * ユーザコントローラの生成 | + | |
- | */ | + | |
- | public function __construct() | + | |
{ | { | ||
- | | + | $this-> |
- | | + | } |
- | + | | |
- | // トランザクションアクション登録 | + | { |
- | $this-> | + | |
+ | } | ||
+ | catch(\Exception $e) | ||
+ | { | ||
+ | throw new ApplicationException(__('messages.error.db.update' | ||
} | } | ||
- | ... | + | |
+ | return redirect(route(" | ||
} | } | ||
</ | </ | ||
- | * transactional()を使って3つのアクション( '' | + | この例では、ユーザモデル( < |
+ | |||
+ | アクションがしなければならないことは、モデルの例外を捕捉して、ApplicationException をスローすることだけです。フレームワークは ApplicationException またはそれを親に持つ例外のみを捕捉します。それ以外の例外は、集約エラーハンドラーによって補足されシステムエラーになります。即ち、フレームワークは、ApplicationException のみ前画面に戻すリダイレクトレスポンスを生成します。 | ||
+ | |||
+ | モデルは次の場合に ApplicationException をスローします: | ||
+ | |||
+ | * 楽観的ロック例外が発生した場合( '' | ||
+ | * 対象レコードが存在しない場合(レコード更新時および削除時) | ||
+ | |||
+ | アクションでは、これ以外の例外が発生した場合は、パースエラーなどの | ||
+ | |||
+ | === クエリーの例外処理 === | ||
+ | |||
+ | 通常、トランザクションは更新系の処理で設定するするので、クエリーで発生した全ての例外は集約エラーハンドラで処理されエラー画面が表示されます。この状況を避けたい場合は、次の何れかの選択になるでしょう。 | ||
+ | |||
+ | * クエリーのアクションにもトランザクションを設定する | ||
+ | * アクション内のcatchブロックでエラーメッセージ付きの入力ページをレンダリングする | ||
\\ | \\ | ||