登録ユーザーのログイン・ログアウトの次は、実際にユーザーをユーザーDBに登録するためのロジックを開発してみます。
今回の流れ
今回の作業概要は以下のとおりです。
- ユーザーがID・メールアドレス・パスワード・ユーザー名を入力。登録ボタンを押すと、ユーザーDBに登録される
- 登録の際、ユーザーIDとメールアドレスの重複をチェックする。重複データがあった場合はエラーメッセージを表示して再入力を促す。
- 登録の際に、データのエスケープ処理を行い、SQLインジェクションを回避する
実行結果
入力フォーム
入力データが無い状態で登録ボタンが押された場合
入力データが重複していた場合
入力が完了した場合
データ登録ロジックと、ユーザー情報入力フォーム
ユーザーのデータ登録は、引き続き、PEAR::AUTHのメソッドを使います。
PEAR::AUTHには、ユーザー情報をデータベースに登録するためのメソッド「addUser()」が存在します。
このメソッドを利用して、DB登録を行います。
addUserの用法は、引数としてユーザーID、ユーザーパスワード、その他登録用のDBカラム名と、対応する登録データを引き渡す形になっています。ユーザー登録フォームを作ってデータを渡し、addUserでDBに引き渡せば良さそうです。
require_once("Auth/Auth.php");
$params = array(
"dsn" => "mysqli://pear:peartest@localhost/pear",
"table" => "auth",
"usernamecol" => "username",
"passwordcol" => "password",);
$myAuth = new Auth("DB",$params,"");
$myAuth -> addUser("$username", "$password",
array("email" => "$email", "uname" => "$uname")
);
ただ、フォームから入力されたデータをそのままDB登録すると、既存のユーザーID、メールアドレスと重複することがありえます。
このため、入力データのチェック用ファイル「registChech.php」を作成、インクルードし、入力内容をチェック。DB内のユーザーデータと照合して、重複チェックを行います。
同時に、ユーザーID、メールアドレスが空ではないか、チェックを行います。
ユーザー情報の取得には、PEAR::DBを利用しました。
DBに登録されているユーザー情報をPEAR::DBで検索し、すでに登録済みかどうかをチェックする形にしてみました。
registCheck.php
<?php
/* 入力されたユーザーIDとパスワードを変数に取得 */
$username = $_POST["username"];
$email = $_POST["email"];
/* PEAR::DBを利用してユーザー名とメールアドレスの有無を取得
すでに存在する場合、各変数にユーザーId、メールアドレスのみの配列が生成される
require_once("DB.php");
$dsn = "mysqli://pear:peartest@localhost/pear";
$myDB = DB::connect($dsn);
$user_exist = $myDB -> getRow("SELECT username FROM auth WHERE username='$username' ");
$email_exist = $myDB -> getRow("SELECT email FROM auth WHERE email='$email' ");
/* エラーメッセージ用変数 $regist_error 初期化 */
unset($regist_error);
/* データ登録モードの場合、処理に入る */
if ($_POST["mode"] == check ) {
/* 入力されたIDが空か、もしくは登録済みでないかをチェック */
if(empty($username)) {
$regist_error = "IDは必須です。<br />";
} elseif (!empty($user_exist)) {
$regist_error .= "IDに入力した ".$username."はすでに使用されています。<br />";
}
/* 入力されたメールアドレスが空か、もしくは登録済みでないかをチェック */
if(empty($email)) {
$regist_error .= "emailは必須です。<br />";
} elseif (!empty($email_exist)) {
$regist_error .= "メールアドレスに入力した ".$email."はすでに使用されています。<br />";
}
}
?>
PEAR::DBは、すでに古いライブラリで、一般的にはPEAR::MDB2の利用を推奨しているようですが、今回は勉強中であること、ベースとなるPEAR::DBを触っておいても損はないだろう、という理由から、PEAR::DBを利用しています。
データ登録時には、SQLインジェクションを避けるために、一度入力データをエスケープ処理します。
エスケープ処理には、mysql_real_escape_string関数を利用しました。
mysql_real_escape_string関数のマニュアルページを見ると、利用時にはMySQLに接続する必要があるようなので、エスケープ処理の前後に、接続=>切断の処理を行います。
/* データチェック後、エラーメッセージ変数
$regist_errorが空の場合=エラーがなかった場合
及び、フォーム入力後=hiddenで渡された値がcheckだった場合
データ登録を実行 */
if ($_POST['mode'] == check && empty($regist_error)) {
/* 登録情報のエスケープ処理を行ってデータベースに登録 */
$conn = mysql_connect("localhost", "pear", "peartest");
mysql_select_db(auth);
if (get_magic_quotes_gpc()) {
$username = stripslashes($_POST["username"]);
$email = stripslashes($_POST["email"]);
$password = stripslashes($_POST["password"]);
$uname = stripslashes($_POST["uname"]);
}
$username = mysql_real_escape_string($username);
$email = mysql_real_escape_string($email);
$passsword = mysql_real_escape_string($password);
$uname = mysql_real_escape_string($uname);
mysql_close($conn);
require_once("Auth/Auth.php");
$params = array(
"dsn" => "mysqli://pear:peartest@localhost/pear",
"table" => "auth",
"usernamecol" => "username",
"passwordcol" => "password",);
$myAuth = new Auth("DB",$params,"");
$myAuth -> addUser("$username", "$password",
array("email" => "$email", "uname" => "$uname")
);
流れをまとめると
- registForm.phpで、登録フォームを表示
- 入力データが存在した場合 (フォームがサブミットされた場合) 、registCheck.phpで入力データを検証。
- 入力データに不備があった場合、変数「$error_mesage」にエラーデータを登録。
- 変数$error_mesageが真だった場合=登録データにエラーがあった場合、エラー表示して、再入力を促す
- エラーがなかった場合、データ登録を実行し、登録完了メッセージを変数「$regist_complete」に登録して、表示を行う
というフローになります。
regist.Form.php
<?php
/* データチェックルーチンを読み込み */
include "registCheck.php";
/* データチェック後、エラーメッセージ変数
$regist_errorが空の場合=エラーがなかった場合
及び、フォーム入力後=hiddenで渡された値がcheckだった場合
データ登録を実行 */
if ($_POST['mode'] == check && empty($regist_error)) {
/* 登録情報のエスケープ処理を行ってデータベースに登録 */
$conn = mysql_connect("localhost", "pear", "peartest");
mysql_select_db(auth);
if (get_magic_quotes_gpc()) {
$username = stripslashes($_POST["username"]);
$email = stripslashes($_POST["email"]);
$password = stripslashes($_POST["password"]);
$uname = stripslashes($_POST["uname"]);
}
$username = mysql_real_escape_string($username);
$email = mysql_real_escape_string($email);
$passsword = mysql_real_escape_string($password);
$uname = mysql_real_escape_string($uname);
mysql_close($conn);
require_once("Auth/Auth.php");
$params = array(
"dsn" => "mysqli://pear:peartest@localhost/pear",
"table" => "auth",
"usernamecol" => "username",
"passwordcol" => "password",);
$myAuth = new Auth("DB",$params,"");
$myAuth -> addUser("$username", "$password",
array("email" => "$email", "uname" => "$uname")
);
$regist_complete = "情報を登録しました。登録情報でログインできます。<br />";
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>情報登録ページ</title>
</head>
<body>
<h1>プロフィールの入力・更新</h1>
<?php
if (isset($regist_error)) {
print ("<p><font color=\"red\">".$regist_error."</font></p>");
} elseif (isset($regist_complete) ){
print ("<p><font color=\"red\">".$regist_complete."</font></p>");
}
?>
<form action="<? print($_SERVER['PHP_SELF']) ?>" method="post">
<input type="hidden" name="mode" value="check">
<table>
<tr>
<th>id:</th>
<td><input type="text" name="username" size="20"></td>
</tr>
<tr>
<th>Email:</th>
<td><input type="text" name="email" size="20"></td>
</tr>
<tr>
<th>パスワード:</th>
<td><input type="password" name="password" size="20"></td>
</tr>
<tr>
<th>表示名</th>
<td><input type="text" name="uname" size="20"></td>
</tr>
</table>
<input type="submit" value="登録する">
</form>
</body>
</html>
フローチャート
今回の概要をフローチャートにすると、以下のようになるでしょうか。
(フローチャート作成の練習で書いてみました。誤りを見つけた方は、ご指摘いただけると幸いです)
次回は入力データのベリファイを実装
今回のルーチンでは、重複チェックとブランクチェックのみを行っています。次回は、各項目の入力値をそれぞれ検証するためのルーチンを加えていきます。
今回の疑問
PEAR::AUTH、PEAR::DB、MySQL接続を、それぞればらばらに実行しているけど、もう少し良い方法ないだろうか。
今回はPEAR::DBを使っているが、PEAR::MDB2 に書き換える場合の修正点チェック
データ重複チェックの際に、わざわざPEAR::DBで配列を生成しているけど、これって問題ない?ユーザー情報のチェックは、素直にSQLでセレクト文を書いて、一致確認をしたほうが良いのかな?
ユーザーデータの重複チェックについては、他の方法がないか要検討。
phpのアプリは、初期のphp設定が、かなり重要な気がする。(magic_quote_gpcの設定など)