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 等も利用している)。それらについては公式ドキュメントが充実しているので、適宜参照していただくと良いだろう。