35歳からの中二病エンジニア

社寺・鉄道・アニメを愛でるウェブ技術者の呟き

Laravelのルーティングをアノテーションで指定する

Laravelのルーティングは、設定ファイル(routes.php)に記述するのが標準のやり方である。だが、僕は個人的にルーティングに関しては「設定より規約」でやりたい質である。そこで、わざわざ設定ファイルを見に行く、或いは作るという事をやらずに済むような方法を探す事となった。

Laravel Collective

laravelcollective.com

理想としているのは、何もしなくてもコントローラー名とアクション名からデフォルトのルーティングを組み立ててくれるというものなのだが、それを実現できるような既存の仕組みは見当たらなかった。しかし、これを利用すればコントローラー上にアノテーションを記述する事でルーティングを指定できるというので、利用してみた。インストールするのは、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 等も利用している)。それらについては公式ドキュメントが充実しているので、適宜参照していただくと良いだろう。

laravelcollective.com