本文へジャンプ

[Laravel5] 管理者/ユーザーのログインを別々に実装する(MultiAuth)

Posted by mio.satoh

以前このブログでは「Laravel初心者講座」というシリーズを連載?していたのですが、あの頃はまだLaravel4でした。
しばらく扱っていなかった間にLaravel5になり、すっかり垢抜けて進化してしまいました。
今回、仕事でちょっとしたログイン絡みのシステム構築の機会があったので、久しぶりにLaravelネタを投下してみます。

管理者とユーザのログイン窓口が別で、それぞれ管理したい。よくあるパターンですね。
Laravel5の標準のログイン認証パッケージはよくできているのですが、多少面倒なステップを踏む必要があります。

インストールは省略します!

初期設定

インストールディレクトリの.envを編集して、DBの接続情報を入力しておきます。

DB_CONNECTION=mysql
DB_HOST=MySQLのhost
DB_PORT=MySQLのポート番号
DB_DATABASE=DB名
DB_USERNAME=DBユーザー名
DB_PASSWORD=DBパスワード

DBテーブルとモデルの作成

マイグレーション(DBテーブル作成)

コマンド2行で終わります。

$ php artisan make:auth
$ php artisan migrate

管理者用テーブル作成

上記のマイグレーションが終わると、標準のUserモデルがapp/User.phpに、標準のUserテーブルがDBに生成された状態になります。
これを元に、Adminモデル/テーブルも作成していきます。

Adminsテーブル作成

database/migrations に生成されている
yyyy_mm_dd_000000_create_users_table.php を複製して、
yyyy_mm_dd_000000_create_admins_table.php にリネームします。
中身の"users"という文字列をすべて"admins"に置き換えます。
もう一度migrateすると、adminsテーブルが追加されるはずです。

$ php artisan migrate

Adminモデル作成

app/User.phpを複製して、app/Admin.phpにリネームします。
中身の"user"という文字列をすべて"admin"に置き換えます。

これで、標準のユーザモデルと、それを元に作った管理者モデルを使う準備ができました。

config変更

config/auth.phpにログイン認証関係の設定が書かれているのですが、そちらをMultiAuth向けに編集する必要があります。

<?php
return [
    'defaults' => [
        'guard' => 'user', // web→userに変更
        'passwords' => 'users',
    ],

    'guards' => [
        'user' => [ // web→userに変更
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ],

        // ここから追記
        'admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],
        // ここまで追記
    ],

    'providers' => [
        // ここから追記
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],

        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Admin::class,
        ],
        // ここまで追記
    ],

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],

        // ここから追記
        'admins' => [
            'provider' => 'admins',
            'table' => 'password_resets',
            'expire' => 60,
        ],
        // ここまで追記
    ],
];

コントローラ作成

Auth系Controller追加

ログイン処理を司るControllerは、app/Http/Controllers/Authに展開されています。
adminは別処理にしたいので、これも複製して追加していきます。

今回、ユーザーがログインするのはトップページ(/)で、管理者は別に管理ページ(/admin)からログインする形を想定しています。
まず、app/Http/Controllers/Authと並列に、app/Http/Controllers/Adminディレクトリを作成します。
そして、AuthディレクトリをまるごとAdminディレクトリの中に複製します。

Auth系Controller追加

このような構成になりました。

このままでは正しく読み込まれないので、app/Http/Controllers/Admin/Auth内の各Controllerのnamespaceを新しいパスに書き換え、さらに読み込むモデルをUserモデルから先程作っておいたAdminモデルに変更します。

<?php
namespace App\Http\Controllers\Admin\Auth; // namespaceを修正

use App\Http\Controllers\Admin\Auth; // モデルを App\User から変更
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;

class RegisterController extends Controller
{
// 以下省略
?>

この作業をすべてのAdmin/Auth以下のControllerに行います。

HomeController追加

Controller/HomeController.phpController/Adminに複製して、同じようにnamespaceの修正をします。 記載されているmiddlewareやviewの表記もちょこっと弄る必要があります。

<?php
namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class HomeController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth:admin');
    }

    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Contracts\Support\Renderable
     */
    public function index()
    {
        return view('admin.home');
    }
}

ルーティング

仕上げにルーティングの分離です。
ルーティングはroutes/web.phpで設定します。

まず、通常のユーザーログインは以下のような設定にします。

Route::get('/', function () {
    return view('home');
});

// 未ログイン
Route::get('login', 'Auth\LoginController@showLoginForm')->name('login');
Route::post('login', 'Auth\LoginController@login')->name('login');

Route::get('register', 'Auth\RegisterController@showRegisterForm')->name('register');
Route::post('register', 'Auth\RegisterController@register')->name('register');

Route::get('password/rest', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request');

// ログイン済
Route::group(['prefix' => '', 'middleware' => 'auth'], function(){
    Route::post('logout', 'Auth\LoginController@logout')->name('logout');
    Route::get('/', 'HomeController@index')->name('home');
});

上記のように、middlewareにauthを指定しておくと、ログイン済みの場合のルーティングを設定できます。
prefixは、特定のパス以下のルーティングをまとめて設定するものです。
これらを利用して管理者用のルーティングも設定すればよいので、

// 管理者未ログイン
Route::group(['prefix' => 'admin', 'middleware' => 'guest:admin'], function() {
    Route::get('login', 'Admin\Auth\LoginController@showLoginForm')->name('admin.login');
    Route::post('login', 'Admin\Auth\LoginController@login')->name('admin.login');

    Route::get('register', 'Admin\Auth\RegisterController@showRegisterForm')->name('admin.register');
    Route::post('register', 'Admin\Auth\RegisterController@register')->name('admin.register');

    Route::get('password/rest', 'Admin\Auth\ForgotPasswordController@showLinkRequestForm')->name('admin.password.request');
});

// 管理者ログイン済
Route::group(['prefix' => 'admin', 'middleware' => 'auth:admin'], function(){
    Route::post('logout', 'Admin\Auth\LoginController@logout')->name('admin.logout');
    Route::get('/', 'Admin\HomeController@index')->name('home');
});

こんな感じで追記すれば、完成!

まとめ

Laravel5になって、作法も構成もだいぶ変わりましたが、一度掴めてくるとサクサク気持ちよく書き進められるのは4と同じですね。
特に5は今回紹介したauth認証のような標準セットが充実しているので、プログラマーにとっての導入コストは低めだと思います。
私が最初にLaravelを紹介した頃は世の中的にもまだ新参フレームワークという扱いで、これほどスタンダード化するとは思わず、今となっては感慨深いものがあります。こんなに大きくなっちゃって...!
今後もLaravelネタは定期的に投下していきたいと思っております。

参考にしたサイト

https://qiita.com/sola-msr/items/65634826bcedf3ea4ca4 (sola-msr様)
https://www.tech-corgi.com/laravel5-6-multi-auth/ (株式会社CORGI様)

Recent Entries
MD EVENT REPORT
What's Hot?
こんな僕たちの仲間に入りませんか?
Movable Type AWS 移管&アップグレード サービス
乃木坂・六本木 撮影配信スタジオ
すべてのコンテンツ/プラットフォームを、ひとつのコンテンツ管理システムで。