祝：Laravelが5.2で"MultiAuth"に対応！


Laravelは素晴らしいフレームワークです。ほとんど文句はありません。が、唯一の不満がMulti-Authに標準で対応していなかったことです。が、とうとう対応したようなので使ってみます。

>ここでいうMulti-Authとは、認証用のユーザーテーブルとしてusersとadminsと別のテーブルを利用するようなものを意味しています。

これで、[今までの苦労](http://qiita.com/zaburo/items/bc699185b6de12c0413d)も報われます。

##準備

では、認証に使うテーブルを作成するためのmigrateファイルや初期ユーザー登録用のseeder等を作成してみます。作成するものは、

* テーブル（migrateすることにより作成します）
* モデル（driverとしてeloquentを利用するので作成します）
* 初期ユーザー（seederで登録してみます）

###usersテーブル

####migrateファイル

usersテーブル生成用のmigrateファイルは既に、database/migrationsの中に存在していますので、それをそのまま利用します。

####モデル

usersテーブルと紐づくUserモデルは既にapp/User.phpとして存在していますので、それをそのまま利用します。

####UserTableSeeder

usersテーブルにテスト用の初期ユーザーを登録するためのseederを用意します。

```bash
php artisan make:seeder UserTableSeeder
```

とすると、database/seeds以下にUserTableSeeder.phpが生成されますので、それを下記のようにします。

```php
<?php

use Illuminate\Database\Seeder;
use App\User;

class UserTableSeeder extends Seeder
{

    public function run()
    {
        //削除
        User::truncate();

        //User生成
        $user = new User;

        $user->name = "user1";
        $user->email = "user1@user.com";
        $user->password = Hash::make('user1');

        //保存
        $user->save();
    }
}
```

###adminsテーブル

続いてadminsテーブルの準備をしていきます。

####migrateファイル

usersとは違い、adminsテーブル用のmigrateファイルはないので生成します。雛形は、

```bash
php artisan make:migration create_admins_table --create=admins
```

とすることで、生成されます。後は、users用のmigrateファイルを参考にして、下記のようにします。

```php
<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateAdminsTable extends Migration
{

    public function up()
    {
        Schema::create('admins', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password', 60);
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('admins');
    }
}
```

####モデル

モデルを生成します。雛型は、

```bash
php artisan make:model Admin
```

とすることで生成可能です。
User.phpと同じにしてもいいですが、ここでは継承するクラスだけModelからAuthenticatableに変えて置きます。

```php
<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;

class Admin extends Authenticatable
{
    //
}
```

####AdminTableSeeder

seederを用意します。

```php
<?php

use Illuminate\Database\Seeder;
use App\Admin;

class AdminTableSeeder extends Seeder
{
    public function run()
    {
        //削除
        Admin::truncate();

        //Admin生成
        $admin = new Admin;

        $admin->name = "admin1";
        $admin->email = "admin1@admin.com";
        $admin->password = Hash::make('admin1');

        //保存
        $admin->save();
    }
}
```

migrateファイルとseederの準備ができたのでテーブルを作成し、初期データを登録します。

###Migrate

```bash
php artisan migrate
```

###Seeder

```bash
php artisan db:seed
```

これで準備ができました。

##利用してみる

###auth.phpの編集

基本的には、providersとguardsをいじれば大丈夫です。
パスワードリセットを使うのならpasswordsも設定しておきます。

```php
<?php

return [


    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],


    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
        //追加
        'user' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        //追加 for admin
        'admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],
    ],


    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
        //追加 for admin
        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Admin::class,
        ],
    ],


    'passwords' => [
        'users' => [
            'provider' => 'users',
            'email' => 'auth.emails.password',
            'table' => 'password_resets',
            'expire' => 60,
        ],
        //追加 for admin
        'admin' => [
            'provider' => 'admins',
            'email' => 'auth.emails.password',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],

];
```

###動作確認（とりあえず）

毎度の手抜きで、とりあえずroute.phpに記述して動作確認をしてみます。
本当はMiddleware等で実装すべきです（暇な時に追記します。雑なものでよければを[こっち](http://qiita.com/zaburo/items/bc699185b6de12c0413d)に書いてます）。

```php
Route::get('admin',function(){

	//Guardを選択(admin)
	$auth = Auth::guard('admin');
	
	//認証
	if($auth->attempt(['email'=>'admin@admin.com','password'=>'admin1']))
	{
		echo "You are Admin!";
	}else{
		echo "You are not Admin!";
	}
	
	return;

});

Route::get('user',function(){
	
	//Guardを選択(user)
	$auth = Auth::guard('user');
	
	//認証
	if($auth->attempt(['email'=>'user1@user.com','password'=>'user1']))
	{
		echo "You are User!";
	}else{
		echo "You are not User!";
	}
	
	return;
	
});
```

動きました。
Multi-Authが本家に実装されたことで、少しはぐっすり眠れるようになります（追記：ぐっすり眠れませんでした、下記動作確認２をご覧下さい）。

###動作確認２（重要）

メソッド間で認証情報が保持されず？？？という感じでしたが、Laravel5.2から、認証を含むSessionの保持（やCSRF,Cookie等）の処理ポリシーが変わったようで、webミドルウエアを通す必要があるようです。route.phpに新しくgroupが追加されていたので？？？と思っていましたが、このためのようです。


なので、下記のソースでは、/adminで取得した認証は、/hogeに共有されません。

```php
Route::get('admin',function(){
    	
	if(Auth::guard('admin')->attempt(['email'=>'admin1@admin.com','password'=>'admin1']))
	{
		return redirect('hoge');

	}else{

		return "You are not admin.";

	}

});

Route::get('hoge',function(){

	return Auth::guard('admin')->user()->name;

});
```


認証やSession状態を共有するためには、下記の様に、webミドルウエアを適用する必要があるようです。

```php
Route::group(['middleware' => ['web']], function () {

    //
    Route::get('admin',function(){
    	
    	if(Auth::guard('admin')->attempt(['email'=>'admin1@admin.com','password'=>'admin1']))
    	{
    		return redirect('hoge');

    	}else{

    		return "You are not admin.";

    	}

    });

    Route::get('hoge',function(){

    	return Auth::guard('admin')->user()->name;

    });
});
```

[ここ](https://laracasts.com/discuss/channels/laravel/auth-session-killed-after-redirect-laravel-52)に書いてありました。

###動作確認３
ログインした後のページは、adminしかアクセスさせない場合、authミドルウエアにguardを指定すればOK

```php

class AdminController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth:admin', ['except' => 'index']);
    }

}
```

guardが指定されない場合は、auth.phpで設定された値が使用されます。

```php
'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
],
```

###メモ

5.2からroute.phpに、

```php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| This route group applies the "web" middleware group to every route
| it contains. The "web" middleware group is defined in your HTTP
| kernel and includes session state, CSRF protection, and more.
|
*/

Route::group(['middleware' => ['web']], function () {

});
```

という記述が追加されています。HTTP系の処理は基本、webミドルウエアをかませるほうがいいようです。