この記事について
下記の記事の続編です。
Undocumented Laravel (1) Routing 編 - Qiita
Laravel 公式サイトに載ってない機能について紹介します。
に載ってない機能について紹介します。
今回は、コントローラー編です。
公式ドキュメントに載ってないということは、後方互換を考慮せずに変更されることもありうるので、使用にあたっては熟慮されることをオススメします。
役に立つか立たないか、ご自身の目でお確かめください。
環境
- PHP 7.1.4
- Laravel 5.5.25
目次
- 基底クラスを継承しない Controller の振る舞い
- callAction で共通処理
1. 基底クラスを継承しない Controller の振る舞い
下記の記事の補足のようなかんじになってしまいますが、もう少し深掘りしてみます。
参考)LaravelのControllerクラスって何やってるの? - Qiita
下記の部分です。
ここで言う「基底クラス」は、app/Http/Controllers/Controller.php で定義されているクラスのことです。
中身はシンプルで、
extends Illuminate\Routing\Controller
して、
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
しているだけです。
基底クラスを継承しない Controller をつくったとき、どうやって代替するか、下記に示します。
1. Controller を継承しないとどうなるか
$this->middleware()
が使えなくなります。
代替案
ルーティング定義のところで定義しましょう。
例えば HomeController で、
$this->middleware('auth');
のように定義していたら、
Route::get('/home', 'HomeController@index')->middleware('auth');
のようにします。
2. AuthorizesRequests が使えなくなるとどうなるか
$this->authorize()
が使えなくなります。
代替案
Gate::authorize()
を使いましょう。
$this->authorize('update-post');
と書いていた部分は、
Gate::authorize('update-post');
とすれば同等になります。
3. DispatchesJobs
$this->dispatch()
が使えなくなります。
代替案
Job 自体にディスパッチさせるか、dispatch()
ヘルパーを使いましょう。
これは単純で、
$this->dispatch(new SomeJob());
となっているところを、
SomeJob::dispatch();
とするか、
dispatch(new SomeJob());
とすればOKです。
4. ValidatesRequests
$this->vaildate()
が使えなくなります。
代替案
FormRequest クラスを使いましょう。
まぁ、Controller にバリデーション書くと Fat Controller 警察のひとたちに怒られますので、継承するしないにかかわらず、FormRequest でやっておくのが無難です。
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
とかやっている箇所があったら、
public function rules()
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
に移しましょう。
2. callAction で共通処理
おまけです。
Illuminate\Routing\Controller クラスに、 callAction
というメソッドがあって、なんだこれと思ったので、使い途を考えてみました。
Illuminate\Routing\ControllerDispatcher クラスで以下のように呼ばれています。
public function dispatch(Route $route, $controller, $method)
{
$parameters = $this->resolveClassMethodDependencies(
$route->parametersWithoutNulls(), $controller, $method
);
if (method_exists($controller, 'callAction')) {
return $controller->callAction($method, $parameters);
}
return $controller->{$method}(...array_values($parameters));
}
シグネチャは下記です。
Response function callAction(string $method, array $parameters)
アクションメソッドで DI してると、上の $parameters
には、インスタンス化されて入ってくるので、これらを使って何かする処理が書けそうです。
class SomeController extends Controller
{
public function callAction(string $method, array $parameters)
{
$someService = $parameters[0];
$someModel = $parameters[1];
//
return parent::callAction($method, [$someService, $someModel]);
}
public function index(SomeService $service, SomeModel $model)
{
//
}
}
最後に親の callAction()
を呼べばOKです。
まとめ
至れり尽くせりな印象の Laravel ですが、フレームワークが提供する Controller の機能は驚くほど少なかったです(最初は Controller 編をスキップしようかと思ったくらい)。
他にも公式ドキュメントに載っていないコントローラー周りの便利な機能があれば、ぜひ、コメント欄にてご紹介ください