基本的なコントローラー
全ルートのロジックをたった一つのroutes.php
ファイルで定義するより、コントローラークラスを使い構造化して利用したいと、考えていることでしょう。コントローラーは関連したルートごとのロジックをクラスにまとめると同時に、自動的な依存の注入など、より高度なフレームワークの機能が使える利点があります。
基本的にコントローラーはapp/controllers
ディレクトリーに設置されます。このディレクトリーはデフォルトでcomposer.json
ファイルにclassmap
オプションとして登録されています。しかし、コントローラーは技術的に、どのディレクトリー・サブディレクトリーにも設置可能です。ディスク上のコントローラークラスファイルの位置に、ルートの宣言は依存していません。そのため、Composerがコントローラークラスをオートロードできるのであれば、どこにでもお好きな場所へどうぞ!
コントローラークラスの一例です。
class UserController extends BaseController {
/**
* 指定されたユーザーのプロファイルを表示する
*/
public function showProfile($id)
{
$user = User::find($id);
return View::make('user.profile', array('user' => $user));
}
}
全てのコントローラーはBaseController
クラスを拡張する必要があります。BaseController
はapp/controllers
ディレクトリーの中にあり、共通のコントローラーロジックを記述するために使用できます。BaseController
はフレームワークのController
クラスを拡張しています。では、このコントローラールートを呼び出してみましょう。
Route::get('user/{id}', 'UserController@showProfile');
もし、あなたがサブフォルダーでネストし、PHP名前空間で体系付けられたコントローラーを採用しているのなら、簡単に完全なクラス名をルートで使用することができます。
Route::get('foo', 'Namespace\FooController@method');
注目:LaravelではPHPクラスのオートローディングにComposerを利用しています。ですからComposerが認識する場所であれば、ファイルシステム上のどこにでもコントローラーを置くことが可能です。コントローラーディレクトリーは、アプリケーションのファイル構造をあなたに強いるものではありません。コントローラーへのルーティングは、ファイルシステムより完全に分離されています。
コントローラールートに名前を付けることもできます。
Route::get('foo', array('uses' => 'FooController@method',
'as' => 'name'));
コントローラーアクションに対するURLを生成するには、URL::action
メソッドか、action
ヘルパメソッドを使用してください。
$url = URL::action('FooController@method');
$url = action('FooController@method');
現在実行中のコントローラーアクションの名前を取得するにはcurrentRouteAction
メソッドを使用します。
$action = Route::currentRouteAction();
コントローラーフィルター
コントローラールートに、「普通」のルートと同じようにフィルターを指定することができます。
Route::get('profile', array('before' => 'auth',
'uses' => 'UserController@showProfile'));
その一方で、コントローラーの内部でフィルターを指定することも可能です。
class UserController extends BaseController {
/**
* 新しいUserControllerインスタンスの生成
*/
public function __construct()
{
$this->beforeFilter('auth', array('except' => 'getLogin'));
$this->beforeFilter('csrf', array('on' => 'post'));
$this->afterFilter('log', array('only' =>
array('fooAction', 'barAction')));
}
}
更に、無名関数を使用しインラインでコントローラーフィルターを指定することもできます。
class UserController extends BaseController {
/**
* 新しいUserControllerインスタンスの生成
*/
public function __construct()
{
$this->beforeFilter(function()
{
//
});
}
}
フィルターとしてコントローラのメソッドを使用したい場合は、フィルターの定義に@
記法を使用してください。
class UserController extends BaseController {
/**
* 新しいUserControllerインスタンスの生成
*/
public function __construct()
{
$this->beforeFilter('@filterRequests');
}
/**
* やってきたリクエストをフィルターにかける
*/
public function filterRequests($route, $request)
{
//
}
}
暗黙的なコントローラー
Laravelでは一つのルート定義だけで、コントローラーの全アクションを簡単に処理できます。最初にRoute::controller
メソッドでルートを定義します。
Route::controller('users', 'UserController');
controller
メソッドは2つの引数を取ります。最初はコントローラーが処理するベースのURIで、2つ目はコントローラーのクラス名です。続いて対応するHTTP動詞名をプレフィックスに使用した、コントローラメソッドを付け加えてください。
class UserController extends BaseController {
public function getIndex()
{
//
}
public function postProfile()
{
//
}
public function anyLogin()
{
//
}
}
index
メソッドはコントローラーが処理するURIのルートに対応します。この例ではusers
です。
もしコントローラアクションを複数の単語で命名するのでしたら、「ダッシュ」で分離したURIでアクセスできます。例えば下のコントローラーアクション、UserController
は、users/admin-profile
というURIに対応します。
public function getAdminProfile() {}
RESTフルリソースコントローラー
リソースフルコントローラーはリソースに関するRESTフルコントローラーを簡単にしてくれます。例えば、アプリケーションにより管理されている「写真(phots)」を管理するコントローラーを作成するとしましょう。Artisanコマンドラインでcreate:make
を実行し、Route::resource
メソッドでルートを定義すれば、そのようなコントローラを素早く生成できます。
コマンドラインでコントローラーを作成するには、以下のコマンドを実行してください。
php artisan controller:make PhotoController
そのコントローラーをリソースフルなルートとして登録しましょう。
Route::resource('photo', 'PhotoController');
この一行の宣言だけで写真リソースに対するRESTフルな多彩のアクションを処理する複数のルートを作成できます。更に、生成されたコントローラーには処理する変数とURIが指し示す各アクションのスタブメソッドが予め含まれています。
リソースフルコントローラーにより処理されるアクション
変数 | パス | アクション | Route Name |
---|---|---|---|
GET | /リソース名 | index | resource.index |
GET | /リソース名/create | create | resource.create |
POST | /リソース名 | store | resource.store |
GET | /リソース名/{resource} | show | resource.show |
GET | /リソース名/{resource}/edit | edit | resource.edit |
PUT/PATCH | /リソース名/{resource} | update | resource.update |
DELETE | /リソース名/{resource} | destroy | resource.destroy |
リソースアクションの一部のみを取り扱いたい場合もあると思います。
php artisan controller:make PhotoController --only=index,show
php artisan controller:make PhotoController --except=index
更に、処理するルートに関して、アクションの一部を指定したいこともあるでしょう。
Route::resource('photo', 'PhotoController',
array('only' => array('index', 'show')));
Route::resource('photo', 'PhotoController',
array('except' => array('create', 'store', 'update', 'destroy')));
デフォルトで、すべてのリソースコントローラーアクションはルート名を持ちます。しかしオプションにnames
配列を渡すことで、こうした名前をオーバーライドすることもできます。
Route::resource('photo', 'PhotoController',
array('names' => array('create' => 'photo.build')));
ネストしたリソースコントローラーの処理
「ネスト」したリソースコントローラーには、ルート宣言で「ドット」記法を使用してください。
Route::resource('photos.comments', 'PhotoCommentController');
これにより、「ネスト」したリソースが登録され、photos/{photoResource}/comments/{commentResource}
のURLにアクセスできるようになります。
class PhotoCommentController extends BaseController {
public function show($photoId, $commentId)
{
//
}
}
リソースコントローラーにルートを追加する
デフォルトのリソースルート以外のルートをリソースコントローラーへ追加する必要がある場合は、Route::resource
の呼び出しより前に定義する必要があります。
Route::get('photos/popular', 'PhotoController@method');
Route::resource('photos', 'PhotoController');
見つからないメソッドの処理
Route::controller
を使用する場合、指定されたコントローラで一致するメソッドが見つからないときに呼び出されるバックアップメソッドを定義することが可能です。メソッド名はmissingMethod
と付け、メソッド名とリクエストのパラメーターを配列で受け取ります。
バックアップメソッドを定義する
public function missingMethod($parameters = array())
{
//
}
リソースコントローラーを使用する場合は、見つからないメソッドを処理するため、コントローラーに__call
マジックメソッドを定義します。