WinRoadのLaravel4初心者講座

次世代PHPフレームワークのLaravel4を初心者向けに解説して参ります。

Winroad徒然草の管理人がお届けします
Laravel4

ログインフィルターの作成及び適用

前回は、Sentry2でログインする方法を調べましたので、今回は、Sentry2 用のログインフィルターの作成及び適用について調べてみたいと思います。

デフォルトのフィルター

その前にまず、Laravel4のデフォルトのフィルターを見てみましょう。

laravel/app/filters.php

<?php
App::before(function($request){
//
 });
 App::after(function($request, $response){
 //
 });
Route::filter('auth', function(){
if (Auth::guest()) return Redirect::guest('login');
 });
Route::filter('auth.basic', function(){
 return Auth::basic();
 });
Route::filter('guest', function(){
if (Auth::check()) return Redirect::to('/');
 });
Route::filter('csrf', function(){
if (Session::token() != Input::get('_token')){
 throw new Illuminate\Session\TokenMismatchException;
 }
 });
  • 2-7行目:アプリケーションの開始前と終了後に動作させるイベントを定義することが出来ます。ここには、プロジェクト全体で適用するフィルターを作成します。
  • 8-10行目:Laravel標準添付の認証フィルターです。Auth::attempt()で認証した場合、適用されます。今回はこれは使用しません。
  • 11-13行目:ベーシック認証を使用するためのフィルターです。
  • 14-16行目:guestフィルターです。authフィルターと逆の働きをしています。authフィルターがログインしていなければ、loginページへリダイレクトしているのに対し、guestフィルターは、ログインしていれば、トップページへ移動するように記述しています。
  • 17-20行目:CSRF対策のためのフィルターです。セッションのトークンとフォームから送信されてきたトークンが異なった場合にトークンエラー(TokenMismaatchExcrption)がスローされる(投げかけられる)ように作られていますので、例外処理用のロジックを作成した方が無難だと思います。

Sentry用のフィルター

それでは、filters.phpにSentry2用のフィルターを追加します。

//Sentryフィルター
Route::filter('sentry', function(){
 if ( ! Sentry::check()) return Redirect::to('login');
});
    • 2行目:’sentry’名(任意)でフィルターを作成します。
    • 3行目:Sentry::checkメソッドは、Sentry2を使用して認証している事を確認するためのメソッドですので、ここでは、もし認証されていなければ、Loginコントローラのindex.phpへ移動するように指定しています。

ルーターでフィルターの適用

フィルターを適用するには、ルーター(routes.php)にフィルターを記述する方法と、コントローラにフィルターを記述する方法があります。

まず、先にルーターにフィルターを適用する方法を調べてみます。Route::getメソッドの、第2引数の、’before’にsentryフィルターを指定します。

laravel/app/routes.php

Route::get('/', array('before'=>'sentry',function()
{
 return View::make('hello');
}));

コントローラにフィルターの適用

次に、コントローラ内にフィルターを適用する方法を調べてみます。コントローラ内にフィルターを適用するには、コンストラクターに記述します。

//コンストラクター
 public function __construct(){
 $this->beforeFilter('sentry');
 $this->beforeFilter('csrf',array('on'=>'post'));
 }
  •  3行目:beroreFilterメソッドの第1引数で適用するフィルターを指定します。第2引数は、オプションで’only’や’except’プロパティを指定することが出来ます。

    //例:getIndexのみにフィルターを適用する
    $this->beforeFilter(‘sentry’,’only’=>getIndex());

  • 4行目:CSRFフィルターの適用例です。POST送信時のみに適用されます。

try~catch構文でログイン処理

Sentry2のドキュメントにあるように、try~catch構文でログイン処理する方法を調べてみたいと思います。

  1. try~catch構文は、PHP5.0以降に採用された構文で例外処理を行います。tryで例外の発生する可能性のあるロジックを記述し、例外を捕捉したら、発生した例外に応じてcatch以降のロジックを実行します。
  2. 下記にpostIndex()を記述します。
    laravel/app/controllers/LoginController.php

    public function postIndex(){
     try{
     //フォームからemailとpasswordの連想配列を取得
     $login=Input::only('email','password');
     //ログインの実行
     $user=Sentry::authenticate($login,Input::get('remember'));
     //ログイン後トップページへリダイレクト
     return Redirect::to('/');
     }
     //例外を捕捉したら
     catch (Cartalyst\Sentry\Users\LoginRequiredException $e){
     //元のページへリダイレクト
     return Redirect::back()
     ->withErrors(array('warning'=>'E-mailとパスワードを入力して下さい'))
     ->withInput();
     }
     catch (Cartalyst\Sentry\Users\PasswordRequiredException $e){
     return Redirect::back()
     ->withErrors(array('warning'=>'パスワードを入力して下さい'))
     ->withInput();
     }
     catch (Cartalyst\Sentry\Users\UserNotActivatedException $e){
     return Redirect::back()
     ->withErrors(array('warning'=>'アクティベートされていません'))
     ->withInput();
     }
     catch (Cartalyst\Sentry\Users\UserNotFoundException $e){
     return Redirect::back()
     ->withErrors(array('warning'=>'該当者がいません'))
     ->withInput();
     }
     }
    • 6行目:Sentry::authenticate()メソッドで認証を行います。第1引数に、認証するための情報(emailとpassoword)を指定します。第2引数には、ログイン状態を保持するかどうかをtrue又は、falseで指定します。
    • 6行目:Input::get()メソッドで受け取った値を第2引数に指定しています。checkboxにチェックを入れていれば下記のようにブラウザにcartalyst_sentry名のクッキー(有効期限:5年間)を保存します。
      laravel012
    • 8行目:ログイン後にトップページへ移動します。
    • 11行目:必須ログイン情報が無かったら、元のページ(ログインページ)へ移動します。
    • 14-15行目:エラー情報と入力値を保持したままリダイレクトします。
    • 17行目:パスワードが入力されていなかったら、元のページへリダイレクトします。
    • 22行目:emailとパスワードが一致していてもアクティベートされていなければ、元のページへリダイレクトします。アクティベートされていない場合は、元のページでは無く、別のページを用意しておいた方がいいかもしれませんね。
    • 27行目:ユーザーが見つからなかった場合に、元のページへリダイレクトします。
  3. ビューファイルを下記のように修正します。
    laravel/app/views/login/index.blade.php

    <!doctype html>
     <html>
     <head>
     <meta charset="utf-8">
     <title>Login</title>
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     {{HTML::style('tbs/css/bootstrap.min.css')}}
     {{HTML::style('tbs/css/signin.css')}}</head>
    <body>
    <div class="container">
     {{Form::open(array('url'=>'login/index','class'=>'form-signin'))}}
     <h2 class="form-signin-heading">会員専用サイト</h2>
     {{Form::text('email','',array('class'=>'form-control','placeholder'=>'E-mail'))}}
     {{Form::password('password',array('class'=>'form-control','placeholder'=>'Password'))}}
     @if($errors->has('warning'))
     <div class="alert alert-danger">
     {{$errors->first('warning')}}
     </div>
     @endif
     {{Form::checkbox('remember',1,true)}} ログイン状態を保持する<br><br>
     {{Form::submit('ログイン',array('class'=>'btn btn-lg btn-primary btn-block'))}}
     {{Form::close()}}
    </div> <!-- /container -->
    </body>
     </html>
    • 修正(追加)箇所は、15-19行目です。
    • エラーがあった場合、下記のように入力フィールドの下にエラー文字を表示します。
    • 尚、Sentry2では、コントローラでwithInput()を指定して、リダイレクトすると、ビューファイルは何も変更せずに、元の入力値を表示します。つまり、Form::text()メソッドの第2引数に、Input::old(‘email’)を記述しなくても元の入力値を表示します。
      laravel013
  4. emailとpasswordが一致した場合、トップページへ移動します。
  5. 尚、このままでは、只単にユーザー認証して、トップページへ移動しただけです。認証機能を使うためには、認証していない人は、指定のページへアクセスできないようにしなければなりません。
  6. 次回は、認証していない人は指定のページへアクセスできないようにフィルターをかける方法を調べてみたいと思います。

ログインフォームから値を受け取る

1. 前回作成したログインフォームからどのような値が送信されているのかを調べるために、postIndex()を下記のように作成します。

laravel/app/controllers/LoginController.php

public function postIndex(){
 dd(Input::all());
 }
  • dd()は、指定された変数の内容を表示し、スクリプトの実行を停止するヘルパー関数です。PHPのvar_dump()関数と同じような働きをします。※正確には、return var_dump();と同じ働きをします。
  • Input::allメソッドは、フォームから送信された全入力値の連想配列を取得します。

2. フォームから、値を入力して送信してみます。

laravel010

3. 下記のように表示されました。

laravel011

4. フォームから送信されたデータには”_token”、”email”、”password”、”remember”があります。このうちの”_token”は、前回作成したフォームの中には含まれていませんでした。

5. laravelのフォームはフォーム内に隠しフィールド(hidden)としてトークンを作成しなくても、自動的にフォームから送信されるような仕様に変更されています(※Form::openで開始した場合)

6. 『Formクラスの基礎』の中で、CSRF対策として明示的にForm::tokenメソッドで、トークンを隠しフィールドとして追加するように記述していますが、この処理は不要となります。

7. ですので、フォームを作成するときには、トークンについては一切考慮する必要はありません。

8. 只、受け取ったコントローラ内で処理する必要がありますが、実際問題としてこの処理もフィルターに任せることによりCSRF対策に関しては全く考慮する必要がなくなります。

フォームからの値の受け取り方

フォームから値を受け取るには、下記のようなInputクラスを使用します。

  • Input::get(‘フィールド名’)
    指定のフィールドの値のみを取得します。
  • Input::all()
    フォーム送信された全てのフィールド名と値を連想配列として取得します。
  • Input::only(‘フィールド1′,’フィールド2’,….)
    フォームから送信されたデータのうち、指定されたフィールド名と値の連想配列を取得します。
  • Input::excetp(フィールド1,フィールド2,….)
    フォームから送信された全てのデータの中から、引数に指定されたフィールド以外のデータのフィールド名と値の連想配列を取得します。
  • Input::has(‘フィールド名’)
    指定のフィールド名の入力値が存在するかどうかを確認するのに使用します。

ちょっと横道にそれましたが、次回こそは、Sentry2を使用してのログイン方法をご紹介します。

ログインフォームの作成

1. ログインコントローラを作成して、まず最初にログインフォームを表示するためのgetIndex()メソッドを作成します。

laravel/app/controllers/LoginController.php

<?php
 class LoginController extends BaseController{
 //ログインフォームの表示
 public function getIndex(){
 return View::make('login/index');
 }
 }

2. ログイン用のフォームを作成するのですが、その前にTwitter Bootstrap3.0を使う準備をしたいと思います。

3. 下記のサイトからTwitter Bootstrap3.0をダウンロードして適当な箇所に解凍して下さい。

http://getbootstrap.com/

4. ダウンロードしたTwitter Bootstrap3.0は、かなりのフォルダ数、ファイル数がありますので、Twitter Bootstrap2.0系統を使用していた人でも、戸惑いそうです。

5. distフォルダ内にあるフォルダ(css、js、font)フォルダをpublic/tbsフォルダにコピーします。※tbsフォルダは事前に作成しておきます。

6. そして、今回ログインフォーム用に使用するCSSファイルをexamples/singin/singin.cssから、public/tbs/cssフォルダ内に保存します。

laravel08

7.  signin.cssファイルと同じフォルダ内にあるindex.htmlをindex.blade.php名に変更して、中身を下記のように修正して、viewsフォルダにloginフォルダを作成し、その中に保存します。

laravel/app/views/login/index.blade.php

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Login</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{{HTML::style('tbs/css/bootstrap.min.css')}}
{{HTML::style('tbs/css/signin.css')}}
</head>
<body>
<div class="container">
{{Form::open(array('url'=>'login/index','class'=>'form-signin'))}}
 <h2 class="form-signin-heading">会員専用サイト</h2>
{{Form::text('email','',array('class'=>'form-control','placeholder'=>'E-mailアドレス'))}}
{{Form::password('password',array('class'=>'form-control','placeholder'=>'パスワード'))}}
{{Form::checkbox('remember',1,true)}} ログイン状態を保持する<br><br>
{{Form::submit('ログイン',array('class'=>'btn btn-lg btn-primary btn-block'))}}
{{Form::close()}}
</div> <!-- /container -->
</body>
</html>
  • 7行目:HTML::styleメソッドは、CSSファイルをpublicフォルダより読み込みます。ここでは、publicフォルダ内にtbsフォルダ作成し、その中にTwitter Bootstrap3.0のcssフォルダを保存しています。
  • 12行目:Form::openメソッドで、フォームを開始します。’url’でログインコントローラのgetIndexメソッドを指定しています。
  • 14行目:Form::textメソッドで、テキストフィールドを作成します。第1引数にフィールド名、第2引数はデフォルト値、第3引数は、パラメーターを連想配列で指定します。
  • 15行目:Form::passwordメソッドで、パスワードフィールドを作成します。第1引数に、パスワードフィールド名、第2引数にパラメーターを連想配列で指定します。
  • 16行目:Form::checkboxメソッドで、チェックボックスを作成します。第1引数にチェックボックス名、第2引数に値を指定します。第3引数はオプションで、trueを指定すると、初期値がチェック状態になります。
  • 17行目:Form::submitメソッドで、Submitボタンを作成します。第1引数に表示名、第2引数にはパラメーターを連想配列で指定します。

8. ブラウザからアクセスしてみます。下記のようになりました。Twitter Bootstrapはデザインの苦手な人でも簡単にレイアウトが作成できますので、便利ですね。※会員専用サイトの文字の箇所には、サイトのロゴを作成して表示するようにした方が良さそうですね。

laravel009

9. 次回は、フォームから受け取った値を処理する方法をご紹介します。

基本グループ及び初期ユーザーの作成

Sentry2のログインコントローラを作成する前に、基本グループ(Administrators、Moderators、Users)及び初期ユーザーを作成したいと思います。

1. RESTフルなコントローラとして、SetupControllerを下記のように作成します。

laravel/app/controllers/SetupController.php

<?php
 class SetupController extends BaseController {
public function getIndex(){
 return View::make('setup/index');
 }
 public function getSentryInit(){
 try{
 $group = Sentry::getGroupProvider()->create(array(
 'name' => 'Administrators',
 'permissions' => array(
 'admin' => 1,
 'user' => 1,
 ),
 ));
 }
 catch (Cartalyst\Sentry\Groups\GroupExistsException $e)
 {
 echo 'Administratorグループは既に存在しています。<br>';
 }
try
 {
 // Moderatorグループの作成
 $group = Sentry::getGroupProvider()->create(array(
 'name' => 'Moderators',
 'permissions' => array(
 'admin.view' => 1,
 'user.create' => 1,
 'user.delete' => 0,
 'user.view' => 1,
 'user.update' => 1,
 ),
 ));
 }
 catch (Cartalyst\Sentry\Groups\GroupExistsException $e)
 {
 echo 'Moderatorsグループは既に存在しています。<br>';
 }
try
 {
 // Userグループの作成
 $group = Sentry::getGroupProvider()->create(array(
 'name' => 'Users',
 'permissions' => array(
 'admin' => 0,
 'user.create' => 1,
 'user.delete' => 0,
 'user.view' => 1,
 'user.update' => 1,
 ),
 ));
 }
 catch (Cartalyst\Sentry\Groups\GroupExistsException $e)
 {
 echo 'Usersグループは既に存在しています。<br>';
 }
try
 {
 // ユーザーの作成
 $user = Sentry::getUserProvider()->create(array(
 'email' => 'winroad@gmail.com',
 'password' => 'winroad',
 'activated' => 1,
 ));
 //グループIDを使用してグループを検索
 $adminGroup = Sentry::getGroupProvider()->findById(1);
 // ユーザーにadminグループを割り当てる
 $user->addGroup($adminGroup);
 }
 catch (Cartalyst\Sentry\Users\UserExistsException $e)
 {
 echo 'このログインユーザーは存在します。<br>';
 }
 }
 }
  •  6行目:getSentryInit()のようなキャメル記法にブラウザからアクセスするには、setup/sentry-initという風に単語間をハイフンで繋ぎます。
  • 8行目:Sentryでは、グループ関連のデータを処理するには、getGroupProvider()で、インスタンス化してから、メソッドチェーンで処理を記述します。
  • 59行目:上記と同様にユーザー関連のデータを処理するには、getUserProvider()で、インスタンス化します。

2. ルーターにRESTフルコントローラを登録します。

laravel/app/routes.php

Route::controller('setup','SetupController');

3. ビューファイルを下記のように作成します。

laravel/app/views/setup/index.blade.php

<!doctype html>
 <html>
 <head>
 <meta charset="utf-8">
 <title>Setup</title>
 </head>
<body>
 {{HTML::link('setup/sentry-init','初期グループ及びユーザーの作成')}}
 </body>
 </html>

4. ブラウザから直接アドレスを入力してもいいのですが、せっかく作成したビューファイル(setup/index.blade.php)から、リンクをクリックします。

5. phpMyAdminを確認すると下記のようにグループとユーザーが作成されています。

laravel06

 

laravel007

 

基本グループと初期ユーザーを作成しましたので、次回は、Loginコントローラを作成したいと思います。

 

Sentry2の導入

Senty2はLaravel4で使用できる高機能認証パッケージでLaravel以外にFuelPHP、CodeIgntiterでも使用できます。パッケージの依存管理は、composerで行っていますので、composer.jsonにパッケージを追加記述して、composer updateを実行し、プロバイダーの追加とエイリアスの追加を行えば、使用できるようになります。

詳細は、Winroad徒然草の「Laravel4でSentry2パッケージの追加」、「Sentry2でデータベーステーブルの作成」を参照していただければ分かると思いますが、、簡単に手順を記載しておきます。

  1. composer.jsonに追加記述
    "cartalyst/sentry":"2.0.*"
  2. composer updateの実行
    laravelをインストールしているルートフォルダ(ディレクトリ)へ移動して、コマンドプロンプトからcomposer updateを実行します。
  3. app/config/app.phpにプロバイダーの追加記述
    環境ファイルapp.phpの115行目にプロバイダーを追加します。

    'Cartalyst\Sentry\SenryServiceProvider',
  4. Senty::メソッド名で、使用できるようにするために同じくapp.phpの180行目にエイリアスを追加します。
    'Sentry'=>'Cartalyst\Sentry\Facades\Laravel\Sentry',
  5. データベーステーブルの作成
    ルートフォルダ(ディレクトリ)へ移動して、Artisanコマンドで、データベーステーブルを作成します。

    php artisan migrate --package=cartalyst/sentry

    ※packageの前のハイフォンは2個です。
    ※Artisanコマンドが初めての方は、先にmigrationsテーブルを作成して下さい。

    php artisan migrate:install
  6. 基本となるのグループを作成します。※最低AdninistratorsグループとUsersグループは作成した方がいいと思います。
  7. Adminユーザーを作成します。
  8. Loginコントローラーの作成
    ルーターでログイン用のロジックを作成してもいいのですが、Login関連のメソッドを作成するために、Loginコントローラを作成します。
  9. Loginフィルターの作成
    ログインしたユーザーによって閲覧できるサイトを振り分けるためにLoginフィルターを作成します。

以上の手順で作成していきたいと思いますが、1~7迄は、WinRoad徒然草でご紹介していますので、より実践的に使用するためにLoginコントローラの作成から次回以降、ご紹介していきたいと思います。

環境設定を調べるには

Laravelの環境設定ファイルは、app/configフォルダ内に設置されています。この環境ファイルの内容を調べるには、Confing::get()メソッドを使用します。

環境設定値へアクセス

Config::get(‘ファイル名.キー’);

Config::getメソッドは、環境設定ファイルへアクセスすることができます。第1引数は、app/configフォルダ以下のファイル名とキーをドット(.)でつないで指定します。第2引数は、オプションで、環境ファイルが存在しないときの、デフォルト値を指定することができます。

基本例

Route::get(‘/’, function(){
return var_dump(Config::get(‘mail.host’));
});

http://localhost/laravel/publicで、下記のように表示します。

string(14) “smtp.gmail.com”

環境設定値をセット

Config::set(‘ファイル名.キー’,’値’);

環境設定値をセットするには、setメソッドを使用します。第1引数には、app/configフォルダ以下のファイル名とキーをドットでつないで、指定します。第2引数には、セットする値を指定します。

基本例

Route::get(‘/’, function(){
echo Config::get(‘app.timezone’).”<br>”;
Config::set(‘app.timezone’, ‘UTC’);
echo Config::get(‘app.timezone’);
});

http://localhost/laravel/publicで、下記のように表示します。

Asia/Tokyo
UTC

実行環境の設定値

上記のConfig::getやConfig::setメソッドは、アプリケーションを実行している設定値を指定しています。つまり、ローカル環境で実行していれば、app/config/localフォルダ内のファイル名.キーにアクセスしていますし、レンタルサーバー環境で実行していれば、app/config/lolipopフォルダ内のファイル名.キーにアクセスしていますので、ご注意ください。

この実行環境の設定値は、「Laravelの初期設定」でも述べていますが、bootstrap/start.phpファイル内の$app->detectEnvironmentの呼び出し名に対応しています。

ログインページの作成

ログインページを作成しましょう。ログインの作成方法は、ルーター内にログイン用のロジックを作成する方法、ログイン専用のコントローラーを作成する方法、ユーザーコントローラー内にログインを作成する方法などがありますが、今回は、UserController内にログインアクションを作成することにします。

UserControllerに下記のコードを追加します。

ログインアクションの作成

app/controllers/UserController.php
 /*
|-----------------------------------------
| ログイン
|-----------------------------------------
*/
 public function getLogin(){
     return View::make('user/login');
 }
 public function postLogin(){
 //受信データの整理
 $inputs=Input::only('email','password');
 //バリデーションの指定
 $rules=array(
 'email'=>'required|email',
 'password'=>'required|min:4',
 );
 //バリデーションチェック
 $val=Validator::make($inputs,$rules);
 //バリデーションNGなら
 if($val->fails()){
 return Redirect::back()
 ->withErrors($val)
 ->withInput();
 }
 //ログイン認証
 $inputs['activate']=1;
 if(Auth::attempt($inputs)){
      return Redirect::intended('/');
 }
     return 'ログインできません';
 }
 /*
|-----------------------------------------
| ログアウト
|-----------------------------------------
*/
 public function getLogout(){
     Auth::logout();
     return Redirect::to('/');
 }
  • 6-9行目:GETで、ビューファイルを表示します。
  • 13-24行目:バリデーション処理を行います。
  • 26行目:ユーザー認証にactivate項目が1の条件を追加します。これで、アクティベートしていないユーザーはログインできなくなります。
  • 28行目:intendedメソッドで、元(ログイン前)のページへリダイレクトします。
  • 37-40行目:ログアウト処理をします。

ログインビューの作成

ログイン用のビューファイルを下記のように作成します。

app/views/user/login.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<title>ログイン</title>
{{ HTML::style('hbp/hpbparts.css') }}
{{ HTML::style('hpb/container_12Ba_2c_top.css') }}
{{ HTML::style('hpb/main_12Ba_2c.css') }}
{{ HTML::style('hpb/user.css') }}
{{ HTML::style('tbs/css/bootstrap.min.css') }}
</head>
<body>
<h3>ログイン</h3>
{{ Form::open() }}
{{ Form::label('email','メール') }}
{{ Form::text('email',Input::old('email','')) }}<br>
@if($errors->has('email'))
<h4 style="color:red;text-align:center">{{ $errors->first('email') }}</h4>
@endif
{{ Form::label('password','パスワード') }}
{{ Form::password('password') }}<br>
@if($errors->has('password'))
<h4 style="color:red;text-align:center">{{ $errors->first('password') }}</h4>
@endif
{{ Form::token() }}
{{ Form::submit('ログイン',array('class'=>'btn btn-success')) }}
{{ Form::close() }}
</body>
</html>
  •  8-11行目:ホームページビルダーで作成したスタイルシートを適用しています。
  • 12行目:Twitter Bootstrapのスタイルシートを適用しています。
  • 27行目:tokenメソッドは忘れずに挿入しましょう。

authフィルターの修正

次にauthフィルターを若干、修正します。

app/filters.php
Route::filter('auth', function(){
    if (Auth::guest()) return Redirect::guest('user/login');
});
  • authフィルターが、認証していないときの移動先が、’login’だったのを、’user/login’に変更しています。

これで、簡単ではありますが、ユーザー認証は完成しました。後は、ユーザーのRoleによって、アクセスできるページやアクションを制限したりする事が出来ますので、各自の条件に応じて作成してみて下さい。

尚、Laravelにはデフォルトで、パスワードリマインダーが付属していますが、後日調べてご報告したいと思います。

ビューファイルの作成

新規ユーザー作成用のcreateビューファイルを下記のように作成します。

app/views/user/create.blade.php
@extends('layouts.hpb')
@section('content')
<h2>ユーザー新規作成</h2>
{{ Form::open() }}
{{ Form::label('name','氏名') }}
{{ Form::text('name',Input::old('name','')) }}
@if($errors->has('name'))
<h3 style="color:red;text-align:center">{{ $errors->first('name') }}</h3>
@endif
{{ Form::label('email','メール') }}
{{ Form::text('email',Input::old('email','')) }}<br>
@if($errors->has('email'))
<h3 style="color:red;text-align:center">{{ $errors->first('email') }}</h3>
@endif
{{ Form::label('password','パスワード') }}
{{ Form::password('password') }}<br>
@if($errors->has('password'))
<h3 style="color:red;text-align:center">{{ $errors->first('password') }}</h3>
@endif
{{-- Form::token() --}}
{{ Form::submit('新規作成',array('class'=>'btn btn-success')) }}
{{ Form::close() }}
@stop

アクティベートビューファイルの作成

アクティベート用のビューファイルを下記のように作成します。

app/views/emails/auth/acrivate.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
</head>
<body>
<h2>アクティベート手続き</h2>

<div>
<h3>{{ $username }}さん、ようこそ!</h3>
<p>あなたのユーザー登録申請を受け付けました。</p>
<p>下記のURLをクリックすると、新規ユーザー作成手続きが、完了します。</p>
<p>{{ URL::to('user/activate', array($onepass)) }}</p>
<p>ありがとうございました。</p>
</div>
</body>
</html>

Userコントローラーの作成

ユーザーの個人ページの表示や新規作成、アクティベート等の処理をするために、Userコントローラーを作成します。

RESTフルコントローラーの登録

UserコントローラーをRESTフルコントローラーとして登録するために、ルーターに下記のように記述します。

app/routes.php

Route::controller(‘user’,’UserController’);

Userコントローラーの作成

Userコントローラーを下記のように作成します。

app/controllers/UserController.php
<?php
class UserController extends BaseController{
/*
|----------------------------------------
| コンストラクター
|----------------------------------------
*/
 public function __construct(){
 //authフィルター
 $this->beforeFilter('auth',array(
 //フィルター適用の指定
 'only'=>array('getIndex')));
 //全POSTにcsrfフィルターの適用
 $this->beforeFilter('csrf',array('on'=>'post'));
 }
/*
|------------------------------------
| TOPページ(authフィルターの適用)
|------------------------------------
*/
 public function getIndex(){
 echo 'ようこそ'.Auth::user()->name.'さん<br>';
 echo '<h1>ユーザーのTOPページです。</h1>';
 echo '<ul>';
 echo '<li>'.HTML::link('/','サイトのTOP').'</li>';
 echo '<li>'.HTML::link('user/logout','ログアウト').'</li>';
 echo '</ul>';
 }
/*
|-----------------------------------
| 新規作成
|-----------------------------------
| 1.GETでビューの表示
| 2.POSTでユーザー仮登録
| 3.仮登録後、アクティベートメールの送信
*/
 //GETの処理
 public function getCreate(){
 return View::make('user/create');
 }
 //POSTの処理
 public function postCreate(){
 //受信データの整理
 $inputs=Input::only('name','email','password');
 //バリデーションの指定
 $rules=array(
 'name'=>'required',
 'email'=>'required|email|unique:users',
 'password'=>'required|min:4',
 );
 //バリデーションチェック
 $val=Validator::make($inputs,$rules);
 //バリデーションNGなら
 if($val->fails()){
 return Redirect::back()
 ->withErrors($val)
 ->withInput();
 }
 //ユーザーの新規作成
 $inputs['onepass']=md5(Input::get('name').time());
 $user=User::create($inputs);
//アクティベートメールの送信
 $data['onepass']=$inputs['onepass'];
 $data['username']=Input::get('name');
 Mail::send('emails.auth.activate',$data,function($m){
 $m->to(Input::get('email'),Input::get('name'))
 ->subject('アクティベート手続き');
 });
 return $user->name.'さん。<br>メールを送信しましたので、アクティベート手続きをして下さい。';
 }
/*
|-----------------------------------------
| アクティベート
|-----------------------------------------
*/
 Public function getActivate($onepass=null){
 //メール添付のワンパス検索OKなら
 if($user=User::where('onepass','=',$onepass)->first()){
 //アクティベート
 $user->activate=1;
 //ワンパスの変更
 $user->onepass=md5($user->username.time());
 //データ保存
 $user->save();
 //トップページへリダイレクト
 return Redirect::to('/');
 //一致するワンパスがなければ
 }else{
 return 'アクティベートできません。';
 }
 }
}
  • 8-15行目:コンストラクターによる初期化処理を行います。
  • 10-12行目:onlyメソッドで、指定のメソッドだけにauthフィルターを掛けます。onlyメソッドの反対は、exceptメソッドで、指定のメソッド以外の全てにフィルターを掛けます。
  • 14行目:HTTPメソッドのPOSTアクションにのみ、csrfフィルターを掛けます。全てのフォームにトークンを埋め込むのを忘れないようにします。
  • 21-28行目:TOPページを表示します。基本的には、View::makeメソッドで、ビューファイルにリンクを張るのが一般的ですが、今回はとりあえず、無名関数内で文字列を表示しています。
  • 38-40行目:GET時のceateアクション、ビューファイル(‘user/create’)を表示します。
  • 42-70行目:POST時のcreateアクションで、ユーザーの新規登録処理をします。
  • 46-58行目:フォームから受け取った値をバリデーション処理します。
  • 60-61行目:バリデーションOKなら、ワンタイムパスワードを作成して、受信データと共に新規ユーザーを作成します。
  • 63-68行目:ワンタイムパスワードのデータと共に、アクティベートメールを送信します。
  • 76-91行目:アクティベート手続きをします。
  • 80行目:usersテーブルにメールに添付したワンタイムパスワードが存在したら、activate項目を1に修正します。
  • 82行目:1度使用したワンタイムパスワードが使用されないように、ワンタイムパスワードを変更します。
  • 89行目:ワンタイムパスワードが一致しない場合は、「アクティベートできません。」の文字列が表示されますが、ビューファイルを作成してビューファイルを表示する方がスマートです。