イントロダクション
全リクエストの処理をたった一つのroutes.phpファイルで定義するよりも、コントローラークラスによるロジックのカテゴリー分けしたいと、皆さん思われるでしょう。HTTPリクエストの関係しているロジックをコントローラーにより、クラス毎にまとめられます。基本的にコントローラーはapp/Http/Controllers
ディレクトリーに設置します。
基本的なコントローラー
コントローラークラスの一例です。
<?php namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
class UserController extends Controller {
/**
* 指定されたユーザーのプロファイルを表示する
*
* @param int $id
* @return Response
*/
public function showProfile($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
コントローラーアクションへのルートは、次のように書きます。
Route::get('user/{id}', 'UserController@showProfile');
注目: 全コントローラーは、ベースコントローラークラスを拡張する必要があります。
コントローラーと名前空間
とても重要な注目ポイントは、コントローラーの完全な名前空間を指定する必要がないことです。「先頭」のApp\Http\Controllers
名前空間に続くクラス名の部分だけを指定しています。デフォルトとして、RouteServiceProvider
がコントローラーの名前空間を指定したルートグループの中で、routes.php
ファイルをロードします。
App\Http\Controllers
ディレクトリーより深く、コントローラのPHP名前空間をネストしたり、組織立てたりする場合でも単に、先頭のApp\Http\Controllers
名前空間からの相対クラス名を指定するだけです。ですから、コントローラーの完全なクラス名がApp\Http\Controllers\Photos\AdminController
ならば、次のようにルートを登録します。
Route::get('foo', 'Photos\AdminController@method');
コントローラールートの命名
クロージャールートと同様に、コントローラールートにも名前が指定できます。
Route::get('foo', ['uses' => 'FooController@method', 'as' => 'name']);
コントローラーアクションへのURL
コントローラーアクションへのURLを生成するときは、action
ヘルパメソッドを使用します。
$url = action('App\Http\Controllers\FooController@method');
コントローラーの名前空間からの相対クラス名の一部だけを使用し、コントローラーアクションへのURLを生成したい場合は、URLジェネレーターへルート名前空間を登録してください。
URL::setRootControllerNamespace('App\Http\Controllers');
$url = action('FooController@method');
実行中のコントローラーアクション名を取得するには、currentRouteAction
メソッドが使えます。
$action = Route::currentRouteAction();
コントローラーミドルウェア
ミドルウェアは、コントローラーアクションに対して、次のように指定します。
Route::get('profile', [
'middleware' => 'auth',
'uses' => 'UserController@showProfile'
]);
また、コントローラーのコンストラクターでも、ミドルウェアを指定できます。
class UserController extends Controller {
/**
* 新しいUserControllerのインスタンスの生成
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log', ['only' => ['fooAction', 'barAction']]);
$this->middleware('subscribed', ['except' => ['fooAction', 'barAction']]);
}
}
暗黙のコントローラー
Laravelでは、一つのルート定義だけで、コントローラーの全アクションを簡単に定義できます。最初に、Route::controller
メソッドで、そのルートを定義します。
Route::controller('users', 'UserController');
controller
メソッドは2つの引数を取ります。最初はコントローラーが処理するURIで、2つ目はコントローラーのクラス名です。次に、対応するHTTP動詞をプリフィックスにし、メソッドをコントローラーに追加してください。
class UserController extends Controller {
public function getIndex()
{
//
}
public function postProfile()
{
//
}
public function anyLogin()
{
//
}
}
index
メソッドは、コントローラーのルートURIに対応します。この場合、users
です。
コントローラーアクションに複数の単語を含める場合は、URIに「ダッシュ」記法を使用し、そのアクションへアクセスできます。例えば、コントローラーアクションがUserController
であれば、users/admin-profile
のURIにレスポンスします。
public function getAdminProfile() {}
ルート名の指定
コントローラーのルートに「名前」を付けたい場合は、controller
メソッドの第3引数で指定してください。
Route::controller('users', 'UserController', [
'anyLogin' => 'user.login',
]);
RESTフルリソースコントローラー
リソースフルコントローラーにより、リソースに関するRESTフルコントローラーを苦労せずに構築できます。例えば、アプリケーションで保存されている「写真(phots)」関係のHTTPリクエストを処理するコントローラーを作成するとしましょう。Artisanコマンドラインでmake:controller
Artisanコマンドを使えば、対応するコントローラをあっという間に生成できます。
php artisan make:controller PhotoController
次に、コントローラーへのリソースフルルートを登録します。
Route::resource('photo', 'PhotoController');
写真リソースの様々なRESTフルアクションを処理する多くのルートが、この1行のルート定義で作り出されます。同時に、生成されたコントローラーには、どのURI/動詞を処理するのかという情報を含んだスタブメソッドが、それぞれのアクションに対して用意されています。
リソースフルコントローラーにより処理されるアクション
動詞 | パス | アクション | ルート名 |
---|---|---|---|
GET | /photo | index | photo.index |
GET | /photo/create | create | photo.create |
POST | /photo | store | photo.store |
GET | /photo/{photo} | show | photo.show |
GET | /photo/{photo}/edit | edit | photo.edit |
PUT/PATCH | /photo/{photo} | update | photo.update |
DELETE | /photo/{photo} | destroy | photo.destroy |
リソースルートのカスタマイズ
さらに、リソースアクションの一部のみを取り扱うことも可能です。
Route::resource('photo', 'PhotoController',
['only' => ['index', 'show']]);
Route::resource('photo', 'PhotoController',
['except' => ['create', 'store', 'update', 'destroy']]);
全てのリソースコントローラーアクションは、デフォルトでルート名を持ちます。しかしオプションにnames
配列を渡すことで、こうした名前をオーバーライドすることもできます。
Route::resource('photo', 'PhotoController',
['names' => ['create' => 'photo.build']]);
ネストしたリソースコントローラーの処理
「ネスト」したリソースコントローラーには、ルート宣言で「ドット」記法を使用してください。
Route::resource('photos.comments', 'PhotoCommentController');
これにより、「ネスト」したリソースが登録され、photos/{photos}/comments/{comments}
のURLにアクセスできるようになります。
class PhotoCommentController extends Controller {
/**
* 特定の写真のコメントを表示する
*
* @param int $photoId
* @param int $commentId
* @return Response
*/
public function show($photoId, $commentId)
{
//
}
}
リソースコントローラーへのルート追加
デフォルトのリソースルート以外のルートをリソースコントローラーへ追加する必要がある場合は、Route::resource
の呼び出しより前に定義する必要があります。
Route::get('photos/popular', 'PhotoController@method');
Route::resource('photos', 'PhotoController');
依存注入とコントローラー
コンストラクターによる注入
Laravelのサービスコンテナは、全コントローラーの依存解決のために使用されています。これにより、コントローラーが必要な依存をコンストラクターにタイプヒントで指定できるのです。
<?php namespace App\Http\Controllers;
use Illuminate\Routing\Controller;
use App\Repositories\UserRepository;
class UserController extends Controller {
/**
* ユーザーリポジトリーインスタンス
*/
protected $users;
/**
* 新しいコントローラーインスタンスの生成
*
* @param UserRepository $users
* @return void
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}
}
もちろん、Laravelの契約もタイプヒントに指定できます。コンテナが依存解決できるものは、タイプヒントに指定できます。
メソッドによる注入
コンストラクターによる注入に加え、コントローラーのメソッドにタイプヒントで依存を指定することもできます。例えば、あるメソッドでRequest
インスタンスをタイプヒントで指定してみましょう。
<?php namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class UserController extends Controller {
/**
* 新しいユーザーの保存
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$name = $request->input('name');
//
}
}
もしコントローラーメソッドで、ルートパラメーターの入力が求められているのでしたら、依存定義の後に続けて、ルート引数を指定するだけです。
<?php namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class UserController extends Controller {
/**
* 指定ユーザーの更新
*
* @param Request $request
* @param int $id
* @return Response
*/
public function update(Request $request, $id)
{
//
}
}
注目: メソッドによる注入はモデルの結合でも同様に動作します。コンテナは結合されたモデルの引数と、注入すべきモデルを賢く判断します。
ルートキャッシュ
アプリケーションがコントローラールートだけを使用していれば、Laravelのルートキャッシュを利用できる利点があります。ルートキャッシュを使用すれば、アプリケーションの全ルートを登録するのに必要な時間を劇的に減らすことができます。ある場合には、ルート登録が100倍も早くなります!ルートキャッシュを登録するには、route:catch
Arisanコマンドを実行するだけです。
php artisan route:cache
これだけです!キャッシュされたルートファイルは、app/Http/routes.php
ファイルの代わりに使用されるようになります。その代わりに、新しいルートを追加するには、キャッシュルートを再構築する必要があります。ですから、プロジェクトの開発期間の最後に、一度だけroute:cache
を実行するほうが良いでしょう。
新しいキャッシュルートのファイルを生成せず削除するためには、route:clear
コマンドを使います。
php artisan route:clear