データベースの設定
ユーザーはグローバル権限のあるものか、今回作るベースに権限のあるものを使用します。 グローバル権限でももちろん問題はないですが、必要なデータベースにのみ権限があるユーザーを使用する方が好ましいです。
データベース名
testData ここは好きなものでOKです。
テーブル
user
id | int(11) | 被り防止のためにAUTO_INCREMENTの設定、primary key設定 |
---|---|---|
name | varchar(10) | |
password | textまたはvarchar | 登録時にハッシュ化を登録するため長めに設定 |
新規登録ページの作成
フォームで入力された値を受け取って、パスワードが一定桁数以上の時(今回は8桁でデモ)にデータベース登録。 パスワードはpassword_hash()を使用しハッシュ化を行ったあとに登録します。 登録完了後は、アラートで登録完了を表示し、メインページへ遷移するようになっています。
<?php // セッション開始 session_start(); // 既にログインしている場合にはメインページに遷移 if (isset($_SESSION['USERID'])) { header('Location: main.php'); exit; } $db['host'] = 'localhost'; $db['user'] = 'root'; $db['pass'] = 'root'; $db['dbname'] = 'testData'; $error = ''; // ログインボタンが押されたら if (isset($_POST['signUp'])) { if (empty($_POST['username'])) { $error = 'ユーザーIDが未入力です。'; }else if (empty($_POST['password'])) { $error = 'パスワードが未入力です。'; } if (!empty($_POST['username']) && !empty($_POST['password'])) { $username = $_POST['username']; $password = $_POST['password']; $dsn = sprintf('mysql: host=%s; dbname=%s; charset=utf8', $db['host'], $db['dbname']); $pdo = new PDO($dsn, $db['user'], $db['pass'], array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION)); // idの重複とパスワードの桁数チェック function cheak($id,$count){ if($count > 0){ throw new Exception('そのユーザーIDは既に使用されています。'); } if ($id < 8) { throw new Exception('パスワードは8桁以上で入力してください。'); } } try{ $sqlname = 'SELECT COUNT(*) FROM user WHERE `name` = '$username''; $ss = $pdo->query($sqlname); $count = $ss->fetchColumn(); $id = strlen($_POST['password']); cheak($id,$count); $stmt = $pdo->prepare('INSERT INTO `user`(`name`, `password`) VALUES (:username, :password)'); $pass = password_hash($password, PASSWORD_DEFAULT); $stmt->bindParam(':username', $username, PDO::PARAM_STR); $stmt->bindParam(':password', $pass, PDO::PARAM_STR); $stmt->execute(); $_SESSION['USERID'] = $username; echo '<script> alert("登録が完了しました。"); location.href="main.php"; </script>'; } catch(Exception $e){ $error = $e->getMessage(); } } } ?> <!DOCTYPE html> <html> <head> <title>新規登録</title> </head> <body> <main> <form id="loginForm" name="loginForm" action="" method="POST"> <p style="color:red;"><?php echo $error ?></p> <label for="username">ユーザーID<br> <input type="text" id="username" name="username" placeholder="ユーザー名を入力" value="<?php if (!empty($_POST["username"])) {echo htmlspecialchars($_POST["username"], ENT_QUOTES);} ?>"> </label><br> <label for="password">パスワード<br> <input type="password" id="password" name="password" value="" placeholder="パスワードを入力">※8桁以上 </label> <input type="submit" id="signUp" name="signUp" value="新規登録" class="btn up"> </form> </main> </body> </html>
ソースの内容について
if (isset($_SESSION['USERID'])) { header('Location: main.php'); exit; }
セッションに値が入っているとき=ログインを既にしているときには、このページを表示しないようにしています。
function cheak($id,$count){ if($count > 0){ throw new Exception('そのユーザーIDは既に使用されています。'); } if ($id < 8) { throw new Exception('パスワードは8桁以上で入力してください。'); } }
下のtryの中から引数を渡して、それぞれIDの重複とパスワードの桁数をチェックしています。 エラーの場合にはthrow new Exception()で例外が出たことを投げ、エラー文をあとのcatchで表示しています。
$stmt = $pdo->prepare('INSERT INTO `user`(`name`, `password`) VALUES (:username, :password)'); $pass = password_hash($password, PASSWORD_DEFAULT); $stmt->bindParam(':username', $username, PDO::PARAM_STR); $stmt->bindParam(':password', $pass, PDO::PARAM_STR); $stmt->execute();
prepare()の値にはパラメータ(:任意の文字列)をおき、実行はパラメータに値が入るまで待機となります。 password_hash()を使用してパスワードハッシュを生成しています。 bindParamは指定した変数を文字列としてパラメータに入れるもので、また、PDO::PARAM_STRは変数の値を文字列として扱うことを宣言するものです。 今回は数値がないので使用してませんが、数値などを登録する場合にはbindValueとPDO::PARAM_INTを使用します。
$_SESSION['USERID'] = $username; echo '<script> alert("登録が完了しました。"); location.href="main.php"; </script>';
セッションに入力されたユーザー名を入れ(=ログイン)、その後アラートを表示し、メインページへ遷移をさせています。 PHPとJavaScriptでは処理するタイミングが違うため、アラート後のリダイレクトもJavaScriptで行う必要があります。
ログインページの作成
ハッシュ化したパスワードをユーザー名を照らし合わせてログインをします。 先ほど同様、ログインをすでにしている場合にはログインページには飛べないようになっています。
<?php // セッション開始 session_start(); // 既にログインしている場合にはメインページに遷移 if (isset($_SESSION["USERID"])) { header('Location: main.php'); exit; } $db['host'] = 'localhost'; $db['user'] = 'root'; $db['pass'] = 'root'; $db['dbname'] = 'testData'; $error = ''; // ログインボタンが押されたら if (isset($_POST['login'])) { if (empty($_POST['username'])) { $error = 'ユーザーIDが未入力です。'; } else if (empty($_POST['password'])) { $error = 'パスワードが未入力です。'; } if (!empty($_POST['username']) && !empty($_POST['password'])) { $username = $_POST['username']; $dsn = sprintf('mysql: host=%s; dbname=%s; charset=utf8', $db['host'], $db['dbname']); try { $pdo = new PDO($dsn, $db['user'], $db['pass'], array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION)); $stmt = $pdo->prepare('SELECT * FROM user WHERE name = ?'); $stmt->execute(array($username)); $password = $_POST['password']; $result = $stmt->fetch(PDO::FETCH_ASSOC); if (password_verify($password, $result['password'])) { $_SESSION['USERID'] = $username; header('Location: main.php'); exit(); } else { $error = 'ユーザーIDあるいはパスワードに誤りがあります。'; } } catch (PDOException $e) { echo $e->getMessage(); } } } ?> <!DOCTYPE html> <html> <head> <title>ログイン</title> </head> <body> <main> <form id="loginForm" name="loginForm" action="" method="POST"> <p style="color:red;"><?php echo $error ?></p> <br> <label for="username">ユーザーID<br> <input type="text" id="username" name="username" placeholder="ユーザーIDを入力" value="<?php if (!empty($_POST["username"])) {echo htmlspecialchars($_POST["username"], ENT_QUOTES);} ?>"> </label><br> <label for="password">パスワード<br> <input type="password" id="password" name="password" value="" placeholder="パスワードを入力"> </label> <input type="submit" id="login" name="login" value="ログイン"> </form> <p><a href="signup.php">新規登録はこちら</a></p> </main> </body> </html>
ソースの内容について
array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION)
エラーレポートについて例外をスローする設定にしています。 デフォルトはPDO::ERRMODE_SILENTでエラーコードのみが設定されるようになっています。
$result = $stmt->fetch(PDO::FETCH_ASSOC);
結果セットを1行ごとに連想配列形式で取り出し、返り値を $result に代入しています。 $result['name']などで値が表示できます。
password_verify($password, $result['password'])
入力されたパスワードがハッシュ化されたパスワードと一致するかどうかを判定しています。 $passwordの部分には入力されたパスワードが、$result['password']の部分にはハッシュ化パスワードが入ることで判定ができます。 返り値は「true」「false」が返ってきます。
ログイン後のメインページの作成
ログアウトへのリンクと、ログイン状態のチェックをします。
<?php session_start(); // ログイン状態チェック if (!isset($_SESSION["USERID"])) { header("Location: login.php"); exit; } ?> <!DOCTYPE html> <html> <head> <title>メインページ</title> </head> <body> <main> <p>メイン</p> <a href="logout.php">ログアウト</a> </main> </body> </html>
ソースの内容について
if (!isset($_SESSION["USERID"])) { header("Location: login.php"); exit; }
セッションに値がない場合にはログイン画面に遷移させています。
ログアウトページの作成
ログインページへのリンクと、セッションのクリアを行います。
<?php session_start(); // セッションクリア session_destroy(); $error = "ログアウトしました。"; ?> <!doctype html> <html> <head> <title>ログアウト</title> </head> <body> <div><?php echo $error; ?></div> <ul> <li><a href="login.php">ログインページへ</a></li> </ul> </body> </html>
ソースの内容について
session_destroy();
上記の一文でセッションをクリアしています。
まとめ
ソースは下記からダウンロードできます。
PDOの使用&がっつりphp書いたのが初めてなので、間違いやここはこうじゃなくて....って部分があるかと思いますので、気づいた方はコメントまたはご連絡ください!
この記事を読んだ方におすすめ