FuelPHPサイド
FeulBeans 20 : ユーザー認証
FuelPHPにデフォルトで入っている、simpleauthを利用して、ユーザー認証してみましょう。DBの設定、操作なども行いますよ。
FuelPHPのデフォルトの認証システムはSimpleAuth(シンプル・オウサ)です。アクション関数毎にACLのようなアクセス制限を付けられます。
ユーザー情報はDBのテーブルとして管理されます。
この機能はauthパッケージとして提供されています。パッケージは単機能をまとめて、インストールし、使用できるようにするFuelPHPのシステムです。CMSで言えば、プラグインとか拡張機能とか言われる感じですね。プログラム言語で言うなら、ライブラリーに当たります。
今回はアクセス制限は扱わず、ログイン/ログアウトをやってみましょう。
やることは多いですよ。ふんどしを引き締めて…ふんどしは最近あまり無いですね。では、パンツをTバッグのように引き上げて、まいりましょう。
もし、ログインの処理だけを行いたいのなら、これだけでOK です。
続いて、usersテーブルを作成します。
まずはFuelPHPからDBアクセスを出来るように設定ましょう。
configフォルダーのなかにdb.php、そして2つ存在するdevelopmentとproductionフォルダー両方にもdb.phpが含まれています。これは、開発環境と、実機環境では、DBの名前など、異なることが多いでしょうから、分けて設定できるようになっているからです。
configフォルダー直下のdb.phpは基本的で、開発環境でも、実機環境でも良通するような、項目が設定されています。通常は、変更しません。
これでDBアクセスの準備が完了しました。
MySQLに慣れている方は、以下のSQL文で、usersテーブルを作成してください。
CREATE TABLE `users` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`username` VARCHAR( 50 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`password` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`group` INT NOT NULL DEFAULT 1 ,
`email` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`last_login` VARCHAR( 25 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`login_hash` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`profile_fields` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`created_at` INT( 11 ) UNSIGNED NOT NULL ,
UNIQUE (
`username` ,
`email`
)
)
慣れていない方はせっかくですからNetBeansからDBとテーブルを作成してみましょう。NetBeansはDB操作も統合されています。
するとjdbc:mysql://localhost....という項目ができています。ダブルクリックで展開してみましょう。既にDBに登録されているテーブルが表示されます。
たった今、作成したため、接続状態になっています。一度NetBeansを終了し、再度起動したときには、接続されていません。この項目を右クリック、接続を選ぶことで、簡単に接続できます。
この状態から、テーブルを作成したり、内容を閲覧したりできます。ただ、得意不得意があります。例えば、項目の細かい変更をしたい場合であればPHPMyAdminのほうが、設定しやすいです。NetBeansでは、GUIによる設定は機能が限られているからです。
SQLの実行も当然ながら可能です。実際にDBを作成しましょう。
簡単ですね。続いてuserテーブルを作成します。いま、create文を作成したエディターでテーブルを作成してしまうと、SQL文にはDBが指定されていないため、デフォルトのDBに作成されてしまいます。デフォルトのDBは太字で表示されています。まずデフォルトを切り替えましょう。
これで操作対象のデフォルトDBが切り替わりました。続いてusersテーブルを作成します。
これで、準備は完了です。
復習:これからNetBeansでDB操作の練習を続けたい方は、デフォルトのカタログ(操作対象DB)を、今作成したDBにする、接続を作っておくと便利です。
たった今作成したjdbc:mysql...では、接続するたびにデフォルトがMySQLという名前のDBに戻ってしまいます。
デフォルトのDBを指定した、別の接続を作成するためには、サービスウィンドウのデータベース項目の下にある、MySQLサーバーlocalhost:3306:[root]を展開します。すると、過去の接続のDBが表示されていますので、デフォルトにしたいDBを右クリックし、接続を選んでください。新しく接続が作成されます。
各接続はjdbc:mysql:.....という長い名前をわかりやすくリネームできます。いらないものは削除できます。必要なものだけ残し、いらない接続は消しておきましょう。
このまま直ぐに、ログイン処理には行きません。ログイン処理に行っても、ユーザーが登録されていません。ですから、流れ的にはユーザー登録フォームを先に作成しましょう。
まずビューです。views/form/signup.phpです。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title><?php echo $title; ?></title>
</head>
<body>
<?php if (Session::get_flash('notice')) : ?>
<div>
<p><?php
echo implode('</p><p>', (array) Session::get_flash('notice'));
?></p>
</div>
<?php endif; ?>
<h1><?php echo $title; ?></h1>
<?php echo Form::open(Uri::current()); ?>
<?php
echo Form::label('ユーザー名 : ', 'username');
?>
<?php echo Form::input('username', Input::post('username') ? : '', array('size' => 30)); ?>
<?php
echo Form::label('パスワード : ', 'password');
?>
<?php echo Form::password('password', Input::post('password') ? : '', array('size' => 30)); ?>
<?php
echo Form::label('パスワード確認 : ', 'password_confirm');
?>
<?php echo Form::password('password_confirm', Input::post('password_confirm') ? : '', array('size' => 30)); ?>
<?php
echo Form::label('メールアドレス : ', 'email');
?>
<?php echo Form::input('email', Input::post('email') ? : '', array('size' => 30)); ?>
<?php
echo Form::submit('signup', 'ユーザー登録');
?>
<?php echo Form::close(); ?>
</body>
</html>
大きな違いは、パスワード確認用の項目、password_confirmとメールアドレスが追加されたことです。あと、実行ボタンが、ユーザー登録に変わりました。
さて、ビューを先に出した理由は?ピンポン!そうです、以下の回答例を見ず、自分自身で、コントローラーを作成してください。
controllerの下にsignup.phpを作成し、実際の登録はまだ習っていませんから、そこだけは飛ばし、他の部分を組んでください。バリデーションも組んでみましょう。
ぶっちゃけ、login.phpをコピーし、少し修正するだけですよ。
routes.phpも必要に応じ設定し、動作テストも行なってください。localhost/public/signupへアクセスしたら、ユーザー登録フォームが表示されるようにしましょう。正しく動けばOK。私の組んだものと、同じでなくてかまいません。
では、チャレンジしてください。
わからない人は、以下のコードをコピペしてください。views/form/signup.phpです。
<?php
class Controller_Signup extends Controller
{
function action_index()
{
if (Input::method() == 'POST')
{
$val = Validation::forge();
$val->add('username', 'ユーザー名')
->add_rule('trim')
->add_rule('required')
->add_rule('min_length', 3)
->add_rule('max_length', 20)
;
$val->add('password', 'パスワード')
->add_rule('trim')
->add_rule('required')
->add_rule('min_length', 3)
->add_rule('max_length', 20)
;
$val->add('password_confirm', 'パスワード確認')
->add_rule('trim')
->add_rule('required')
->add_rule('match_field', 'password')
;
$val->add('email', 'メールアドレス')
->add_rule('trim')
->add_rule('required')
->add_rule('valid_email')
;
// バリデーション
if ($val->run())
{
// バリデーションOK
Package::load('auth');
// ユーザーの登録、成功時はユーザーidが返ってくる
$user_id = Auth::instance()
->create_user($val->validated('username'), $val->validated('password'), $val->validated('email'), 1);
if ($user_id == true)
{
// 登録成功
Session::set_flash('notice', 'ユーザー登録されました。');
Response::redirect('/'); // ルートへリダイレクト
}
else
{
// 登録失敗
Session::set_flash('notice', 'ユーザー登録に失敗しました。');
Response::redirect('/'); // ルートへリダイレクト
}
}
else
{
// バリデーションNG
Session::set_flash('notice', $val->errors());
} // バリデーション終了
} // ポストチェック終了
$view = View::forge('form/signup');
$view->title = 'ユーザー登録';
return $view;
}
}
続いて、routes.phpの設定をしましょう。(sigupとコントローラークラス名と一緒ですから、設定しなくても動作します。それでも一応設定しておくのは、どのルーティングを設定したかわかりやすいよう、ドキュメント替わりに設定しておきます。)
<?php
return array(
'_root_' => 'login/index', // The default route
'signup' => 'signup/index',
);
では、動作確認です。localhost/public/signupにアクセスしましょう。正しく表示されましたか?入力項目の検査はきちんと行われていますか?
登録されたようなら、usersテーブルの中身を見てみてください。レコードは追加されていますか?
さて、上のコードには問題があります。テストしてわかった人もいるでしょう。ユーザー登録時にユーザー名やメールアドレスが既に登録されていると、エラーで終了してしまいます。
1.1RCと1.1正式版で変更になった点ですね。RCの時までは、失敗したらfalseが返ってきたのですが、1.1正式版では、例外を投げるように変更になっています。
まず、例外の処理コードを入れましょう。変更部分とその前後だけを示します。
// バリデーションOK
// authパッケージのロード
Package::load('auth');
// ユーザーの登録、成功時はユーザーidが返ってくる
try
{
$user_id = Auth::instance()
->create_user($val->validated('username'), $val->validated('password'), $val->validated('email'), 1);
}
catch (SimpleUserUpdateException $e)
{
// この例外が発生した場合、バリデーションにミスがあるということ。
// 見つけづらいので、本来はログを残すべき
$user_id = false;
}
if ($user_id == true)
{
この時点で動作を確認してみましょう。コメントにも書きましたが、この例外が起きることがないように、本来は入力項目をチェックします。今回は、動作を確認してもらうために、この時点で確認してもらっています。必要に応じ、デバッガーを利用し、動作を追いかけてみましょう。
では、抜けているバリデーション処理を入れましょう。ユーザー名とメールアドレスの重複をチェックしていませんでした。その二つを追加します。
ユーザー名とメールアドレスの重複をチェックするためにはDBアクセスが必要です。まだDBアクセスは、このチュートリアルでは扱っていません。設定を行ったばかりですよね。
でも、バリデーションのお話で、独自拡張として紹介したコードがあります。覚えていますか?ドキュメントのサンプルコードです。
テーブルと項目名を指定し、重複がないかチェックするバリデーションでした。まさに、今回にぴったりです。
それを早速使ってみましょう。バリデーションの前記事を参考に、以下を見ないでも修正できそうな方は、チャレンジしてください。
では、まず独自バリデーションのコードを書きます。
classes下にmyvalidation.phpを作成します。controller下ではないですよ。間違わないでください。コントローラーではありませんからね。
<?php
/*
* 指定されたテーブルを項目名で調べ、
* 値がユニークか調べる
*
* 使用法:
*
* $val = Validation::forge();
* $val->add_callable('myvalidation');
*
* $val->add('username', 'ユーザー名')
* ->add_rule('unique'.'users.username');
*
*
*/
class Myvalidation
{
public static function _validation_unique($val, $options)
{
// note ここでエラーメッセージを指定してしまうと、
// その内容で固定されてしまい、
// lang/国コード/validation.phpでの多国語化対応ができなくなる。
list($table, $field) = explode('.', $options);
$result = DB::select("LOWER (\"$field\")")
->where($field, '=', Str::lower($val))
->from($table)->execute();
return!($result->count() > 0);
}
}
次にバリデーションを追加します。
まず、Validation::forge()でバリデーションを生成している行の次に、独自拡張を追加するコードを入れましょう。$val->add_callable('myvalidation');を挿入してください。
次に、usernameに対するバリデーションを一つ加えます。->add_rule('unique', 'users.username')を付け加えてください。
さらに、emailに対しても同様に、付け加えます。->add_rule('unique', 'users.email')を付け加えましょう。
これだけです。さあ、テストしてみましょう。既に登録済みのユーザー名や、メールアドレスを使って、登録しようとしてください。エラーになります。
テスト中に作成したユーザーで、いらないもの、邪魔なものも作ってしまったことでしょう。レコードを削除しておきましょう。
サービスウィンドウからレコード削除が可能です。usersテーブルを右クリック、データを表示を選びます。削除したいレコードを選択し、「選択したレコードを削除」アイコンをクリックするだけです。(もう、詳しく書きませんよ。慣れてください。)
次のログイン処理に向けて、確認しやすいユーザーを作成しておきましょう。
では、本題のログイン処理に入ります。
本題にくまでにエネルギーの80%以上を消費してしまうのが、当チュートリアルの特徴ですよ。:D
ログイン処理の部分のコードを記述します。ログインのコントローラへ組み込んでください。
// 認証チェック
Package::load('auth');
if (Auth::instance()->login($val->validated('username'), $val->validated('password')))
{
// 認証成功
Session::set_flash('notice', 'ログインしました。');
}
else
{
// 認証失敗
Session::set_flash('notice', 'ユーザー名かパスワードが違っているようです。');
}
さて、ログインのテストをしてすぐ気づくことがあります。ログアウトの手段がないことです。
ヒントを出しますので、チャレンジしてくださいね。
ログアウトのコードは、Auth::instance()->logout();です。
ログインをしているかどうかのチェックは、Auth::check()で確認します。ログイン中はture、ログアウト状態はfalseが返されます。
では、チャレンジしてください。
| FuelBeans 18 : バリバリ、バリデーション< 前 | 次 >FuelBeans 21 : アドミンコントローラークラス |
|---|
| < 前 | 次 > |
|---|