イントロダクション
全リクエストの処理をたった一つのroutes.php
ファイルで定義するよりも、コントローラークラスにより組織立てたいと、皆さんも考えるでしょう。関連のあるHTTPリクエストの処理ロジックを一つのクラスへまとめ、グループ分けができます。コントローラーはapp/Http/Controllers
ディレクトリ下に設置します。
基本のコントローラー
これは基本的なコントローラーの一例です。全てのLaravelコントローラーはLaravelにデフォルトで含まれている基本コントローラークラスを拡張します。
<?php
namespace App\Http\Controllers;
use App\User;
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');
これで指定したルートのURIにリクエストが一致すれば、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を生成するにはroute
ヘルパが使用できます。
$url = route('name');
コントローラーミドルウェア
ミドルウェアは、コントローラーアクションに対して、次のように指定します。
Route::get('profile', [
'middleware' => 'auth',
'uses' => 'UserController@showProfile'
]);
またはコントローラーのコンストラクターでも、ミドルウェアを指定できます。middleware
メソッドを使いコントローラーに対しミドルウェアを簡単に指定できます。特定のメソッドに対してだけミドルウェアを指定することも可能です。
class UserController extends Controller
{
/**
* 新しいUserControllerインスタンスの生成
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log', ['only' => [
'fooAction',
'barAction',
]]);
$this->middleware('subscribed', ['except' => [
'fooAction',
'barAction',
]]);
}
}
RESTフルリソースコントローラー
リソースフルコントローラーにより、リソースに関するRESTフルコントローラーを苦労せずに構築できます。例えば、アプリケーションで保存されている「写真(phots)」関係のHTTPリクエストを処理するコントローラーを作成するとしましょう。Artisanコマンドラインでmake:controller
Artisanコマンドを使えば、対応するコントローラをあっという間に生成できます。
php artisan make:controller PhotoController --resource
このArtisanコマンドはapp/Http/Controllers/PhotoController.php
としてコントローラーファイルを生成します。コントローラーは使用可能な各リソース操作に対するメソッドを含んでいます。
次に、コントローラーへのリソースフルルートを登録します。
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 |
HTTPフォームはPUT、PATCH、DELETEリクエストを送れないため、HTTP動詞を指定する_method
隠しフィールドを付ける必要があります。
<input type="hidden" name="_method" value="PUT">
部分的なリソースルート
リソースルートの宣言時に、ルートで処理するアクションの一部を指定可能です。
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
はデフォルトで、リソース名にもとづきリソースルートのルートパラメータを生成します。オプション配列でparameters
を指定することで簡単に、このリソース毎の基本的な命名規約をオーバーライドできます。parameters
配列は、リソース名とパラメータ名の連想配列で指定します。
Route::resource('user', 'AdminUserController', ['parameters' => [
'user' => 'admin_user'
]]);
上記のサンプルコードは、リソースのshow
ルートで次のURIを生成します。
/user/{admin_user}
パラメータ名の配列を渡す代わりに、singular
を指定すると、Laravelはデフォルトのパラメータ名の「単数形」を使用します。
Route::resource('users.photos', 'PhotoController', [
'parameters' => 'singular'
]);
// /users/{user}/photos/{photo}
もしくは、リソースルートパラメータをグローバルに単数形にする、もしくは名前をグローバルにマッピングもできます。
Route::singularResourceParameters();
Route::resourceParameters([
'user' => 'person', 'photo' => 'image'
]);
リソースパラメータをカスタマイズする場合、命名のプライオリティを認識しておくことが重要です。
Route::resource
へ明示的に渡されたパラメータRoute::resourceParameters
でグローバルに設定Route::resource
のparameters
配列にsingular
を設定するか、Route::singularResourceParameters
により設定- デフォルトの命名規則
リソースコントローラーへのルート追加
デフォルトのリソースルート以外のルートをリソースコントローラーへ追加する場合は、Route::resource
の呼び出しより前に定義する必要があります。そうしないと、resource
メソッドにより定義されるルートが、追加のルートより意図に反して優先されます。
Route::get('photos/popular', 'PhotoController@method');
Route::resource('photos', 'PhotoController');
依存注入とコントローラー
コンストラクターインジェクション
全コントローラーの依存を解決するために、Laravelのサービスコンテナが使用されます。これにより、コントローラーが必要な依存をコンストラクターにタイプヒントで指定できるのです。依存クラスは自動的に解決され、コントローラーへインスタンスが注入されます。
<?php
namespace App\Http\Controllers;
use App\Repositories\UserRepository;
class UserController extends Controller
{
/**
* ユーザリポジトリーインスタンス
*/
protected $users;
/**
* 新しいコントローラーインスタンス
*
* @param UserRepository $users
* @return void
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}
}
もちろん、Laravelの契約もタイプヒントに指定できます。コンテナが解決できるのであれば、タイプヒントで指定できます。
メソッドインジェクション
コンストラクターによる注入に加え、コントローラーのメソッドでもタイプヒントにより依存を指定することもできます。たとえば、あるメソッドでIlluminate\Http\Request
インスタンスをタイプヒントにより指定してみましょう。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* 新ユーザの保存
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$name = $request->input('name');
//
}
}
コントローラーメソッドへルートパラメーターによる入力値が渡される場合でも、依存定義の後に続けてルート引数を指定するだけです。たとえば以下のようにルートが定義されていれば:
Route::put('user/{id}', 'UserController@update');
下記のようにIlluminate\Http\Request
をタイプヒントで指定しつつ、コントローラーメソッドで定義しているid
ルートパラメータにアクセスできます。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* 指定ユーザの保存
*
* @param Request $request
* @param string $id
* @return Response
*/
public function update(Request $request, $id)
{
//
}
}
ルートキャッシュ
注意: ルートキャッシュはクロージャベースのルートには動作しません。ルートキャッシュを使用するには、全クロージャルートをコントローラークラスを使用するように変更する必要があります。
アプリケーションがコントローラーベースのルート定義だけを使用しているなら、Laravelのルートキャッシュを利用できる利点があります。ルートキャッシュを使用すれば、アプリケーションの全ルートを登録するのに必要な時間を劇的に減らすことができます。ある場合には、ルート登録が100倍も早くなります。ルートキャッシュを登録するには、route:cache
Arisanコマンドを実行するだけです。
php artisan route:cache
これだけです。キャッシュされたルートファイルは、app/Http/routes.php
ファイルの代わりに使用されるようになります。その代わりに、新しいルートの追加を反映するには、キャッシュしたルートを再構築する必要があります。ですからプロジェクトの開発期間の最後に、一度だけroute:cache
を実行するほうが良いでしょう。
キャッシュルートのファイルを削除するには、route:clear
コマンドを使います。
php artisan route:clear