FuelPHP

FuelPHP - AdminLTEを使ってユーザ認証機能をカンタンに実装する方法

管理システムやサービスには欠かせないユーザ認証機能ですが、fuelphpではauthパッケージを使うとカンタンに実装できます。

authパッケージのsimpleauthという認証機能を使って、ログイン・ログアウト機能を爆速で作っていきましょう。

ユーザ認証機能を作成するために必要な設定

authパッケージを利用するための設定

fuel/app/cofing/config.phpalways_loadormauthを追加する

  'always_laod' => array(
    'packages' => array(
      'orm',
      'auth',
    ),
  ),

sipleauthの設定ファイルをコピー

fuel/packages/auth/configフォルダにあるauth.phpとsimpleauth.phpをfuel/app/configフォルダにコピー

ソルトの設定

auth.phpとsimpleauth.phpのソルトを設定

パスワード生成(パスワード作成)

を使うと便利です

Remember Me 機能の設定

simpleauth.phpのremember_meをtrue
fuel/app/config/crypt.php を作成する

return array(
    'crypto_key' => ';aobfhsajdsjfn;rfgabte',
    'crypto_iv' => ';afoehkbfwfgksfji',
    'crypto_hmac' => 'aa;brephbahjlfskgnvqjarhek',
);

こちらも以下を使うと便利です。

パスワード生成(パスワード作成)

users以外のデータベースを使う場合は以下のように設定

simpleauth.phpのtable_nameの値を書き換え
fuelphp simpleauthを拡張して複数テーブルでのログイン認証 | pbtimes 情報誌

データベーステーブルの作成

AuthパッケージにはSimpleAuthに必要なテーブルを作成するためのマイグレーションファイルが含まれている

oilコマンドを叩くだけで、カンタンに必要なテーブルを生成することができます

oil refine migrate --packages=auth
FUEL_ENV=test oil refine migrate --packages=auth
FUEL_ENV=development oil refine migrate --packages=auth

を叩く

マイグレーションファイルを叩くだけで必要なテーブルが揃う
fuelphpのコンソールを使って、管理者用のユーザを作成してみます。

% oil console
>>> auth::create_user('admin', 'password', 'admin@example.jp', 100);
1
>>>

1と返されたらちゃんと設定できています

ここまでで、認証機能の設定は完了です。

ログイン・ログアウト画面の作成

ちょっとかっこいい管理画面を作りたいので、一瞬だけ脱線してレイアウトを作っていきます。

AdminLTEという管理画面専用のテンプレートがあるので、今回はこれを使います。

AdminLTEの導入

Free Bootstrap Admin Template

このページからダウンロードしてください。

Zipファイルを解凍すると、たくさんファイルとフォルダが入っています。

distpluginsフォルダを、public/assetsにコピーして下さい。

これでAdminLTEのインストールは完了です。

ログイン画面をつくってみよう

AdminLTEをつかってかっこいいログイン画面を作っていきます。

fuel/app/classes/controllerbase.phpを作って下さい。

AdminLTEのCSSやJSをカンタンに呼び出すための設定をしています。

<?php

class Controller_Base extends Controller_Template
{
    public function before()
    {
        parent::before();

        // adminLTEをsetする
        Asset::add_path('assets/dist/', 'css');
        Asset::add_path('assets/dist/', 'js');
        Asset::add_path('assets/dist/', 'img');

        Asset::add_path('assets/plugins/', 'css');
        Asset::add_path('assets/plugins/', 'js');
        Asset::add_path('assets/plugins/', 'img');
    }
}

ログイン後の画面を作っていきます。

ログイン後の画面はホーム画面に当たるので、ルーティングを設定します。

fuel/app/config/routes.phpを以下のように書き換えて下さい。

<?php
return array(
    '_root_'  => 'home/index',  // The default route
    '_404_'   => 'welcome/404',    // The main 404 route

    'hello(/:name)?' => array('welcome/hello', 'name' => 'hello'),
);

このように書き換えることで、http://あなたのドメインにアクセスしたときに、Homeコントローラーのindexアクションに飛ぶように設定できます。

ルーティングの設定が終わったら、実際にログイン後の画面を作っていきます。

まずは、Homeコントローラーをfuel/app/classes/controller/home.phpをつくります。

<?php

class Controller_Home extends Controller_Base
{
    public function before()
    {
        parent::before();
    }

    public function action_index()
    {
        $data = array();
        $this->template->title = "ログイン後の画面";
        $this->template->content = View::forge('home/index', $data);
    }
}

ビューテンプレートをfuel/app/views/template.phpに作成します。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title><?php echo $title; ?></title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" >
    <?php echo Asset::css('css/bootstrap.min.css'); ?>
    <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/redmond/jquery-ui.css" >
    <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/ui-lightness/jquery-ui.css" >
    <!-- ionicons -->
    <link href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet" type="text/css" />
    <!-- adminLTE style -->
    <?php echo Asset::css('css/AdminLTE.min.css'); ?>
    <?php echo Asset::css('css/skins/skin-blue.min.css'); ?>

    <?php echo Asset::js('https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js'); ?>
    <?php echo Asset::js('bootstrap.min.js'); ?>
    <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/i18n/jquery.ui.datepicker-ja.min.js"></script>
    <!-- adminLTE -->
    <?php echo Asset::js('js/app.min.js'); ?>
</head>

<body class="skin-blue fixed sidebar-collapse">
    <!-- .wrapper -->
    <div class="wrapper">

        <?php echo View::forge('header', array()); ?>

        <!-- Content Wrapper. Contains page content -->
        <div class="content-wrapper">

            <!-- .content-alert -->
            <div class="content-alert row">
                <div class="col-md-12">
                    <?php if (Session::get_flash('success')): ?>
                        <div class="alert alert-success">
                            <strong>Success</strong>
                            <p>
                                <?php echo implode('</p><p>', e((array) Session::get_flash('success'))); ?>
                            </p>
                        </div>
                    <?php endif; ?>
                    <?php if (Session::get_flash('error')): ?>
                        <div class="alert alert-danger">
                            <strong>Error</strong>
                            <p>
                                <?php echo implode('</p><p>', e((array) Session::get_flash('error'))); ?>
                            </p>
                        </div>
                    <?php endif; ?>
                </div>
            </div>
            <!-- /.content-alert -->

            <!-- .content-header -->
            <section class="content-header">
                <h1>
                    <?php echo $title; ?>
                </h1>
            </section>
            <!-- /.content-header -->

            <!-- Main content -->
            <section class="content">

                <?php echo $content; ?>

            </section><!-- /.content -->
        </div><!-- /.content-wrapper -->

        <!-- フッター -->
        <footer class="main-footer">
            <div class="pull-right hidden-xs">Version1.0</div>
            <strong>Copyright © 2015</strong>, All rights reserved.
        </footer>
    </div>
    <!-- /.wrapper -->
</body>
</html>

ついでに、ヘッダーもfuel/app/views/header.phpに書いちゃいましょう。

<!-- .main-header -->
<header class="main-header">

    <a href="/" class="logo"><i class="fa fa-star" aria-hidden="true"></i> System</a>

    <!-- Header Navbar: style can be found in header.less -->
    <nav class="navbar navbar-static-top" role="navigation">

        <div class="collapse navbar-collapse" id="navbar-collapse">

            <!-- サイドバー制御 -->
            <a href="" class="sidebar-toggle" data-toggle="offcanvas" role="button">
                <span class="sr-only">Toggle navigation</span>
            </a>

            <ul class="nav navbar-nav">
                <li><a href="">Apple</a></a></li>
                <li><a href="">Pinapple</a></li>
                <li><a href="">Orange</a></li>
            </ul>

            <!-- Navbar Right Menu -->
            <div class="navbar-custom-menu">
                <ul class="nav navbar-nav">

                    <!-- User Account: style can be found in dropdown.less -->
                    <li class="dropdown user user-menu">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                            <?php echo Auth::get_screen_name() . ' さん'; ?> <span class="caret"></span>
                        </a>
                        <ul class="dropdown-menu">
                            <!-- User image -->
                            <li class="user-header">
                                <img src="" class="img-circle" alt="User Image">
                                <p>
                                    <small></small>
                                </p>
                            </li>
                            <!-- Menu Body -->
                            <li class="user-body">
                                <div class="col-xs-4 text-center">
                                    <a href="#">Followers</a>
                                </div>
                                <div class="col-xs-4 text-center">
                                    <a href="#">Sales</a>
                                </div>
                                <div class="col-xs-4 text-center">
                                    <a href="#">Friends</a>
                                </div>
                            </li>
                            <!-- Menu Footer-->
                            <li class="user-footer">
                                <!--
                                <div class="pull-left">
                                    <a href="#" class="btn btn-default btn-flat">Profile</a>
                                </div>
                                -->
                                <div class="pull-right">
                                    <?php echo Html::anchor('/logout', 'ログアウト', array(
                                        'class' => 'btn btn-default btn-flat'
                                    )) ?>
                                </div>
                            </li>
                        </ul>
                    </li>
                    <!-- Control Sidebar Toggle Button -->
                    <li>
                        <a href="#" data-toggle="control-sidebar"><i class="fa fa-gears"></i></a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>
</header>
<!-- /.main-header -->

ログイン後のビューをfuel/app/views/home/index.phpに作りましょ。

トップ画面でっせー

とでも書いておきます。

これで、ログイン後の画面は完了です。

ローカルのドメインhttp://fuelphp.text/にアクセスしてみて下さい。

下のような画面が表示されるはずです!

ここからログイン機能を作っていきます!

fuel/app/classes/controllerに新しくlogin.phpを作ります。

<?php

class Controller_Login extends Controller_Base
{

    public $template = 'template_login';

    public function action_index()
    {

        //すでにログイン済であればログイン後のページへリダイレクト
        Auth::check() and Response::redirect('/');

        //エラーメッセージ用変数初期化
        $error = null;

        //ログイン用のオブジェクト生成
        $auth = Auth::instance();

        //ログインボタンが押されたら、ユーザ名、パスワードをチェックする
        if (Input::post())
        {
            if ($auth->login(Input::post('username'), Input::post('password')))
            {
                // ログイン成功時、ログイン後のページへリダイレクト
                Response::redirect('/');
            } else
            {
                // ログイン失敗時、エラーメッセージ作成
                $error = 'ユーザ名かパスワードに誤りがあります';
            }
        }

        //ビューテンプレートを呼び出し
        $data = array();
        $data['error'] = $error;
        $this->template->title = 'login';
        $this->template->content = View::forge('login/index', $data);
    }

}

次に、ビューテンプレートを作成します。

fuel/views/template_login.phpを新規作成してください。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title><?php echo $title; ?></title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" >
    <?php echo Asset::css('css/bootstrap.min.css'); ?>
    <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/redmond/jquery-ui.css" >
    <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/ui-lightness/jquery-ui.css" >
    <!-- ionicons -->
    <link href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet" type="text/css" />
    <!-- adminLTE style -->
    <?php echo Asset::css('css/AdminLTE.min.css'); ?>
    <?php echo Asset::css('css/skins/skin-black.min.css'); ?>

    <?php echo Asset::js('https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js'); ?>
    <?php echo Asset::js('bootstrap.min.js'); ?>
    <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/i18n/jquery.ui.datepicker-ja.min.js"></script>
    <!-- adminLTE -->
    <?php echo Asset::js('js/app.min.js'); ?>
</head>
<body class="hold-transition login-page">
    <!-- .content-alert -->
    <div class="content-alert row">
        <div class="col-md-12">
            <?php if (Session::get_flash('success')): ?>
                <div class="alert alert-success">
                    <strong>Success</strong>
                    <p>
                        <?php echo implode('</p><p>', e((array) Session::get_flash('success'))); ?>
                    </p>
                </div>
            <?php endif; ?>
            <?php if (Session::get_flash('error')): ?>
                <div class="alert alert-danger">
                    <strong>Error</strong>
                    <p>
                        <?php echo implode('</p><p>', e((array) Session::get_flash('error'))); ?>
                    </p>
                </div>
            <?php endif; ?>
        </div>
    </div>
    <!-- /.content-alert -->

    <?php echo $content; ?>
</body>
</html>

次に、ログイン画面のビューを作成します。

fuel/views/login/index.phpを新規作成し、以下のコードを書いてみましょう。

<div class="login-box">
    <div class="login-box-body">
        <div class="login-logo">
            <a href="/"><b><i class="fa fa-star"></i> System</b></a>
        </div><!-- /.login-logo -->
        <p class="login-box-msg">Sign in to start your session</p>
        <?php echo Form::open(array('class' => ''));?>
            <div class="form-group">
                <?php echo Form::input('username', '', array(
                    'class' => 'form-control input-lg',
                    'placeholder' => 'ログインID'));?>
            </div>
            <div class="form-group">
                <?php echo Form::password('password', '', array(
                    'class' => 'form-control input-lg',
                    'placeholder' => 'パスワード'));?>
            </div>
            <div class="row">
                <div class="col-xs-8">
                </div><!-- /.col -->
                <div class="col-xs-4">
                    <?php echo Form::submit('submit', 'ログイン', array(
                        'class' => 'btn btn-primary btn-block'));?> 
                </div><!-- /.col -->
            </div>
        </form>
        <?php echo Form::close();?>

        <?php if (isset($error)): ?>
            <p class="alert alert-warning"><?php echo $error ?></p>
        <?php endif ?>

    </div><!-- /.login-box-body -->
</div><!-- /.login-box -->

これでログイン画面は完成です。

http://あなたのドメイン.test/loginにアクセスして、以下の画面が表示されればOKです。

今のままでは、ログインしてないユーザでもログイン後の画面にアクセスできてしまうので大問題です。

なので、fuel/app/classes/controller/home.phpを以下のように修正して下さい。

<?php

class Controller_Home extends Controller_Base
{
    public function before()
    {
        parent::before();

        !Auth::check() and Response::redirect('login');
        $this->template->subtitle = '';
    }
}

これで、ログインしていないユーザはログインページにリダイレクトされます。

実際に、http://あなたのドメイン/homeにアクセスしてみてください。

ログイン画面にリダイレクトされれば、OKです。

実はもうこれで完成です。

ログイン機能は実は先程すでにfuel/app/classes/controller/login.phpに書いてました。

コンソールでユーザを作成して、実際にログインしてみましょう。

まず、ターミナルで以下のコマンドを叩いてコンソールを起動し、create_userメソッドを叩いて下さい。

% oil console
>>> auth::create_user('ユーザ名', 'パスワード', 'メールアドレス', 1);
2
>>>

これで、ユーザの作成は完了です。

作成したユーザで実際にログインしてみましょう。

ログイン後の画面が表示されれば完成です!

次に、ログアウト機能を実装してみましょう。

fuel/app/classes/controller/logout.phpを作成し、以下のコードを書いて下さい。

<?php

class Controller_Logout extends Controller
{

    public function action_index()
    {
        $auth = Auth::instance();
        $auth->logout();

        Response::redirect('/');
    }

}

これでログアウト機能は実装完了です。

では、実際に、ちゃんと動くか確かめてみましょう。

今現在は、ログイン状態なので、http://あなたのドメイン/loginにアクセスしても、必ずホーム画面http://あなたのドメイン/homeにリダイレクトされるはずです。

ホーム画面の右上に、〇〇さんと書かれているはずなので、そこをクリックするとログアウトボタンがあるはずです。

このログアウトボタンを押してみて下さい。

ログイン画面にまた戻れば、完成です。

確認として、http://あなたのドメイン/homeにアクセスしてみて下さい。

ログインしていないので遷移できず、ログイン画面にリダイレクトされるはずです。

これで、ログイン・ログアウト機能の完成です!

Gitにコミットしてプッシュ

最後に、いつもどおりコミットとプッシュを忘れずに

git status
git diff
git add .
git commit -m "管理画面のログイン・ログアウト機能を実装"
git push 

まとめ

ちょっと長くなってしまいましたが、AdminLTEを使ってログイン・ログアウト機能をFuelPHPで実装する方法でした!

-FuelPHP