Laravelのルーティングは、設定ファイル(routes.php)に記述するのが標準のやり方である。だが、僕は個人的にルーティングに関しては「設定より規約」でやりたい質である。そこで、わざわざ設定ファイルを見に行く、或いは作るという事をやらずに済むような方法を探す事となった。
Laravel Collective
理想としているのは、何もしなくてもコントローラー名とアクション名からデフォルトのルーティングを組み立ててくれるというものなのだが、それを実現できるような既存の仕組みは見当たらなかった。しかし、これを利用すればコントローラー上にアノテーションを記述する事でルーティングを指定できるというので、利用してみた。インストールするのは、Laravel Collectiveの中でもアノテーション記法を利用するためのパッケージである。
なお、Laravel CollectiveはLaravelコアから取り除かれたコンポーネントをメンテナンスしているプロジェクトである。利用する際にはその点を念頭に置いておきたい。
インストール
まずは以下のComposerパッケージをインストールする。
composer require "laravelcollective/annotations":"^5.3.0"
次に、サービスプロバイダークラスを追加する。 設定内容については後述するので、まずはそのまま貼り付けておこう。
<?php namespace App\Providers; use Collective\Annotations\AnnotationsServiceProvider as ServiceProvider; class AnnotationsServiceProvider extends ServiceProvider { /** * イベントのアノテーションをスキャンするクラス * * @var array */ protected $scanEvents = []; /** * ルーティングのアノテーションをスキャンするクラス * * @var array */ protected $scanRoutes = []; /** * モデルのアノテーションをスキャンするクラス * * @var array */ protected $scanModels = []; /** * local環境の場合に自動的にスキャンするか * * ドキュメントではfalseだが、僕はtrueにしている。 * * @var bool */ protected $scanWhenLocal = true; /** * コントローラーのディレクトリー (Serend\Http\Controllers) から、 * ルーティングのアノテーションを自動的にスキャンするか * * 注意:スキャン対象はControllers直下のみとなる。再帰的ではない。 * * @var bool */ protected $scanControllers = false; /** * 名前空間内の全てのクラスから、 * イベント・ルーティング・モデルのアノテーションを自動的にスキャンするか * * 注意:アプリケーションのサイズに応じて、スキャン時間が長くなる。 * * @var bool */ protected $scanEverything = false; }
最後にお約束通り、サービスプロバイダーを有効にする。
'providers' => [ // ... App\Providers\AnnotationsServiceProvider::class // ... ];
サービスプロバイダーの設定とスキャンについて
サービスプロバイダーの設定で、「スキャン」という言葉が何箇所か出ている。これは何かというと、記述したアノテーションを読み込んで有効化する事である。ルーティングのアノテーションをスキャンする方法は幾つかあるが、先述の通り設定した場合は、次の通りとなる。
- local環境の場合、常に自動的にスキャンされる。
- local環境以外の場合、
php artisan route:scan
コマンドを実行する。
他には protected $scanRoutes
にスキャン対象のコントローラークラスを指定する事もできるが、先の設定にしておけばデプロイ時に毎回artisanコマンドを実行する事で全てのコントローラークラスをスキャンしてくれるので、そちらをお薦めする。
アノテーションの記述方法
@Resource
まずはAPI等を実装する際に役立つ @Resource
について。
/** * @Resource('users') */ class UserController extends Controller { }
これは、以下と同義である。
Route::resource('users', 'UserController');
アクションを絞りたい場合は、 @Resources('users',only={"index","show"})
のように記述すれば良い。
@Get
@Get
はそのままの意味で、HTTPのGetリクエストである。
/** * @Get("users/login") */ public function login(Request $request) { }
これは、以下と同義である。
Route::get('users/login', [ 'as' => 'users.login', 'uses' => 'UserController@login' ]);
@Post, @Put, @Delete, etc...
Get以外のHTTPリクエストについても、同様の記法が利用できる。
おわりに
Laravel Collectiveのアノテーションパッケージを使えば、ルーティングをコントローラー上にアノテーションで記述できる。「設定より規約」的な考え方で、原則としてコントローラー名とアクション名から規則的なルーティングを行っている場合などは特に、扱うファイルが減る分だけ効率的に開発できるだろう。
なお、Laravel Collectiveにはこれ以外にも様々なパッケージがあるし、アノテーションパッケージの中にも紹介し切れていないものがある(実際、僕は @Middleware
等も利用している)。それらについては公式ドキュメントが充実しているので、適宜参照していただくと良いだろう。