速習Larave3(その10)、ルートの保護とエラーページ
タグ: Laravel3
せっかく認証を取り入れましたが、上手く活用していません。十分に活用しましょう。
- ソース:github
Webアプリでなぜ認証が必要かと言えば、特定のページは一般の人に見せたくないからです。ルートを保護するという事ですね。
Laravelでログインしている人だけ、特定のルートのページを使用できるようにするには、authフィルターを使用します。
では、どのルートを保護すれば良いのでしょうか?今まで作成した中でちょっと考えてみましょう。
するとどうやら、削除と追加/更新を保護すれば良いようです。勝手に記事を消されたり、中身を書き換えられたり、むふふな記事を大量に書かれては、困ってしまいます。
とりあえず削除のルートだけに入れてみましょう。
// 記事削除
// フォーム表示
Route::get('/post/delete/(:num)', array( 'as' => 'post-delete', 'before' => 'auth', 'uses' => 'post@delete' ));
// フォーム処理
Route::post('/post/delete/(:num)', array( 'as' => 'post-delete', 'before' => 'csrf|auth', 'uses' => 'post@delete' ));
これで良し。フォーム処理のルートに対し、beforeフィルターを2つ指定しています。その時は縦棒で区切って指定します。伝統的にフィルターは縦棒でつなげるものですからね。
しかしまあ、もうちょっと工夫してかけます。とりあえず、ルートの定義の部分をご覧ください。
/*
* ルーティング定義
*/
// トップページ:一覧表示
Route::get('/', array( 'as' => 'post-index', 'uses' => 'post@index' ));
// 記事表示
Route::get('/post/(:num)', array( 'as' => 'post-show', 'uses' => 'post@show' ));
// ログイン
Route::get('/login', array( 'as' => 'login', 'uses' => 'auth@login' ));
Route::post('/login', array( 'as' => 'login', 'before' => 'csrf', 'uses' => 'auth@login' ));
// ログアウト
Route::get('/logout', array( 'as' => 'logout', 'uses' => 'auth@logout' ));
// ユーザー認証が必要な管理者領域
Route::group(array( 'before' => 'auth' ),
function() {
// 記事追加/編集
// フォーム表示
Route::get('/post/edit/(:num?)',
array( 'as' => 'post-edit', 'uses' => 'post@edit' ));
// フォーム処理
Route::post('/post/edit/(:num?)',
array( 'as' => 'post-edit', 'before' => 'csrf', 'uses' => 'post@edit' ));
// 記事削除
// フォーム表示
Route::get('/post/delete/(:num)',
array( 'as' => 'post-delete', 'uses' => 'post@delete' ));
// フォーム処理
Route::post('/post/delete/(:num)',
array( 'as' => 'post-delete', 'before' => 'csrf', 'uses' => 'post@delete' ));
});
同じフィルターを適用したいルートはグループにまとめられます。今回は認証が必要なルートをグループ化することで、ルートも読みやすくなりました。そう、可読性も大切ですよ。
これできちんと動作するか確認してください。トップページから、ログインしている時としていない時の両方で、削除と更新のリンクをクリックしてください。
authフィルターの定義も同じroutes.phpの中で行われています。
Route::filter('auth', function() {
if ( Auth::guest() )
return Redirect::to_route('login')
->with('message', 'ログインが必要です。');
});
少し変えてあります。デフォルトのコードにメッセージを付けてリダイレクトするようにしています。なにせ、元々のコードは黙ってログインページにリダイレクトするだけですからね。
あと、Redirect::toをRedirect::to_route()に変更しました。toはURLやURIに対して使用します。to_routeはルートの名前を指定します。せっかく名前をルートにつけているのですから、使わなくちゃ損ですよ。
何に役に立つかって?例えばこの場合でしたら、ログインへのURIはloginで分かりやすですよね。でも例えばsuper-login-48などに変えると、このURIを知っている人しかログインできなくなりますよね。ログインのURIが分かっているとチャレンジする不届き者やら出てきますからね。ルート名を指定しておけば、そうしたURIの変更時にアチラコチラのコードをいじる必要が無くなるわけです。ルートの定義のURIパターンだけを変更すれば済みます。
あと新しい事柄は、認証のチェックで使用されている'Auth::guest()'です。これはログインしていない時にtrueになります。
これできちんと動作するか確認してください。トップページから、ログインしている時としていない時の両方で、削除と更新のリンクをクリックしてください。
よしよし。上手く動作していますね。けど、ちょっと引っかかります。よく考えたら、ログインしていない人にリンクを見せなきゃ、もっと良いですよね。
これは一覧ページのビューの変更だけで、可能ですよ。index.blade.phpを修正してください。
@layout('template')
@section('title')
一覧表示
@endsection
@section('content')
<style>
.pagination li {
display: inline;
margin: 0 5px;
}
</style>
<table>
<tr>
<th>タイトル</th>
<th>作成日</th>
@if( Auth::check() )
<th>更新</th>
<th>削除</th>
@endif
</tr>
@foreach($posts as $post)
<tr>
<td>{{ HTML::link_to_route('post-show', $post->title ,array($post->id)) }}</td>
<td>{{ $post->created_at }}</td>
@if( Auth::check() )
<td>{{ HTML::link_to_route('post-edit', '✜', array($post->id)) }}</td>
<td>{{ HTML::link_to_route('post-delete', '✖', array($post->id)) }}</td>
@endif
</tr>
@endforeach
</table>
{{ $link }}
@endsection
Auth::check()を使用して、ログインしている場合のみ、表示するように変更しました。このメソッドはAuth::guest()の逆でして、ログインしている場合のみtrueになります。
これで一覧ページを見てください。ログインしていないときはポスト名と作成日時が表示され、ログインすると更新、削除が表示される便利な一覧ページになりました。CMSのようですね。
せっかく、routes.phpを開いているので、もうひと工夫しましょう。エラーページです。デフォルトのエラーページは英語ですし、しかもデザインが通常のページと異なっています。みっともないですね。これをどうにかしましょう。
元々のエラーページはviews/errorフォルダーの下に、ステータスコードと同じ名前のPHPファイルに記述されています。
そして、エラー時の処理はroutes.php内で記述されており、変更可能です。通常のビューページと同じように作成可能です。まず、404エラーページを作成しましょう。
views/error/404error.blade.phpを作成してください。
@layout('template')
@section('title')
404 ページが見つかりません
@endsection
@section('content')
<h2>404エラー</h2>
<h3>ページが見つかりません。</h3>
<p>お探しのページが見つかりません。</p>
<p>URLを指定した場合は、間違っていないかご確認ください。</p>
@endsection
ご覧の通り。Bladeだって使えちゃいます。内容は短めですよ。お好きに工夫してください。
ビューを出力しているだけですが、元々のエラーステータスコードはそのまま404で送られます。全くLaravelは苦労いらずですね。
あと、500ページは皆さんにお任せします。お好きに作成してください。エラー処理も修正する必要があることをお忘れなく。