速習Larave3(その5)、コントローラー
タグ: Laravel3
コントローラーを使いはじめましょう。
- ソース:github
さて、前回作成したroutes.php
をご覧ください。
随分コードが増えてきました。Laravelの特徴…というか、他のフレームワークでも採用されていますが、コントローラーを使用せず、無名関数を使用してルーティングに直接コードを記述できるようになっています。
これは、全部で数ページのサイトとか、ちょっとしたツールを作成するとか、機能を実験してみるとかには、とても便利に使用できます。
ですが、routes.php
はその名の通り、ルーティングの定義がメインです。まだ、3ページ分のルートしか定義していないのに、全部のルートを見通すのが難しくなっています。
つまり、ルートを調べるという事に関しては、可読性が落ちています。Laravelが折角、読みやすいPHPの世界を作ってくれているのに、その一部の機能を利用して壊しているのです。これはもったいない。対処しましょう。
ということで、今回からコントローラーを使いはじめましょう。どこに入れたらいいか迷うような小さなルーティングの内容ならともかく、可能な限りroutes.php
には、ルートの定義だけ記述して、すっきりさせます。それでなくてもフィルターとか、その他の定義が集まりごちゃごちゃしますからね。
Tips!! その内なるボヤキが聞こえたのか、Laravel4ではフィルターの定義は別ファイルになりました。Laravel3でもファイルを分け、routes.phpでrequireしてすっきりさせる方法は取れます。
まず、コントローラーを作成し、そこに記事に関する操作を移動します。application/controllers/post.php
を作成してください。
<?php class Post_Controller extends Base_Controller { // レストフル動作フラグ public $restful = true; /** * 一覧表示 */ public function get_index() { $posts = Post::order_by('created_at', 'desc')->get(); return view('post.index') ->with('posts', $posts); } /** * 記事表示 */ public function get_show($id) { $post = Post::find($id); if ( $post === null ) { return Redirect::error('404'); } return View::make('post.show') ->with('title', $post->title) ->with('body', $post->body); } /** * 記事追加フォーム表示 */ public function get_add() { return view('post.add'); } /** * 記事追加フォーム処理 */ public function post_add() { // バリディーションルール $rules = array( 'title' => 'required|max:50', 'body' => 'required|max:8000', ); $input = Input::only(array( 'title', 'body' )); $val = Validator::make($input, $rules); if ( $val->passes() ) { // バリデーション通過 // 新ポストの追加 $post = new Post($input); $post->save(); // 続けて追加できるように、 // フォームは空のままリダイレクト return Redirect::to_route('post-add') ->with('message', '記事を追加しました。'); } else { // バリデーション失敗 // バリディーションで生成されたエラーと // フォームに入力された内容を // セッションのフラッシュデーターを通じ // フォームに送る return Redirect::to_route('post-add') ->with_errors($val->errors) ->with_input(); } } }
当然のことながら、前回まで積み上げてきたコードと同じですね。違っているのは関数名が付くことくらいでしょう。
関数名の命名規則は他のフレームワークとよく似ています。通常はプレフィックスにaction_
を付けます。それ以降の名前がアクション名となります。アクション名とはルーティングで指定される名前のことです。
今回はRESTルーティング、RESTフルなルーティングを使用します。これはプレフィックスがリクエストのHTTP変数の名前になる命名規則を使用するという事です。例えばGETメソッドでのアクセスはget_
が頭に付き、POSTメソッドならpost_
です。これを使用するにはコントローラーの$restful
プロパティをtrueにセットします。
続いて、routes.phpを改良しましょう。
<?php /* * ルーティング定義 */ // トップページ:一覧表示 Route::get('/', array( 'as' => 'post-index', 'uses' => 'post@index' )); // 記事表示 Route::get('/post/(:num)', array( 'as' => 'post-show', 'uses' => 'post@show' )); // 記事追加 // フォーム表示 Route::get('/post/add', array( 'as' => 'post-add', 'uses' => 'post@add' )); // フォーム処理 Route::post('/post/add', array( 'as' => 'post-add', 'before' => 'csrf', 'uses' => 'post@add' )); /* * エラー処理 */ Event::listen('404', function() { return Response::error('404'); }); Event::listen('500', function() { return Response::error('500'); }); /* * フィルター定義 */ Route::filter('before', function() { // Do stuff before every request to your application... }); Route::filter('after', function($response) { // Do stuff after every request to your application... }); Route::filter('csrf', function() { if ( Request::forged() ) return Response::error('500'); }); Route::filter('auth', function() { if ( Auth::guest() ) return Redirect::to('login'); }); /* * ビュー・コンポーサー定義 */ View::composer('template', function($view) { $view->warning = isset($view->warning) ? $view->warning : Session::get('warning', false); $view->message = isset($view->message) ? $view->message : Session::get('message', false); });
どうでしょうか。コードが少なくなり、すっきりしました。一番重要なのは先頭のルートの定義が読みやすくなったという事です。これで他の人が呼んでも分かりやすくなりました。他の人の中には、半年後の自分も含まれています。
ルーティングの定義では'as'を使いルート名、'uses'を使いコントローラーとアクションを定義しています。
もし全体をコントローラー/アクションだけで統一するのであれば、ルート名は無理に必要ありません。コントローラー/アクションの指定でリンクを生成できるからです。名前とコントローラー/アクションのどちらでもリンクやURL、URIを生成できるのですが、便利でも両方を混ぜて生成するとごちゃごちゃになりますので、どちらか一方を使用しましょう。
今回は無名関数でのルーティングを完全に使用しないとは決めず、必要に応じて使用し、無名関数のルーティングとコントローラーを両立させようと思います。ですから、ルートには全部名前を付け、その名前でリンクを生成する方針をとっていきます。