こんにちは、MIO webデザインです。
今回は前回に引き続き、『WordPressのようなコメント管理システムを作ってみよう』と思います。
- 対象者
- PHPの基礎がわかる人
- phpMyAdminの使い方がわかる人
前回は入力したコメントをデータベースに保存するプログラムを作りました。
今回は、投稿されたコメントの管理画面……ではなく、管理画面にアクセスするためのログイン機能を作っていきます!
これから作っていくもの
改めまして、簡易コメント管理システム『ふらこめ(necofly comment system)』制作シリーズ第2回です!
WordPressのコメント管理機能をイメージしてくれるとありがたいです。
『ふらこめ』で実装する機能は以下の通り。
- ふらこめで実装する機能
- コメントの受付
- 管理画面でのコメント管理
- コメントの承認・削除・編集・返信機能
- 管理画面へのログイン機能
- 新規管理アカウント取得機能
ざっとこんな感じです!
コメント欄からコメントを受け付けられるのはもちろんのこと、コメントの管理画面も欲しいところですね。
ただ見る人全員が好き勝手管理できたら大変なので、ログイン機能も設置。ついでに新規管理アカウント取得(サインアップ)機能も作ってしまいましょう。

最終的には下記のようなファイル構造になります。
hura_come
├── admin
│ ├── dashboard.php
│ ├── delete.php
│ ├── display.php
│ ├── login.php
│ ├── logout.php
│ ├── reply.php
│ ├── signup.php
│ └── update.php
├── css
│ └── style.css
├── db_info
│ └── db_info.php
├── images
│ └── logo.jpg
└── save_comment.php
では早速作っていきましょう!
今回作るもの – 『ログイン機能』

管理画面にアクセスするときにログイン画面を挟まないと、第三者が勝手にコメントを管理できるようになってしまいます。いただいたコメントを勝手に消されたら嫌なので、ログイン機能を実装した方がいいでしょう。
ふらこめのログイン機能に必要なのは、メールアドレスとパスワードです。
入力したメールアドレスとパスワードがデータベース上に存在したら、管理画面にアクセスできるプログラムを作成していきます。
今回用意するファイルは『login.php』『logout.php』『dashboard.php』の3つです。
下記を参考に3つのファイルを用意しましょう。
hura_come
├── admin
│ ├── dashboard.php
│ ├── login.php
│ └── logout.php
├── css
│ └── style.css
├── db_info
│ └── db_info.php
└── save_comment.php
ファイルが準備できたら、まずはユーザー情報を管理する『user_table』テーブルを作成しましょう。
user_tableテーブルの準備

前回と同じ流れで、hurakomeデータベースにuser_tableテーブルを作成します。必要なカラムは3つ。下記の画像を参考に3つのカラムを作成してください。idにAUTO_INCREMENTの設定をするのをお忘れなく!

手動で作成する以外にも、下記のコードを『SQL』に貼り付けて作成することもできます!
CREATE TABLE IF NOT EXISTS `user_table` (
`id` int(11) NOT NULL,
`email` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(15) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `user_table`
ADD PRIMARY KEY (`id`);
ALTER TABLE `user_table`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=2;
また、今回は最初からログインできるユーザーを設定しておきます。
下記のコードを『SQL』で実行してください。実行すると、メースアドレスがsample@aaa、パスワードが1111のユーザーが追加されます。
INSERT INTO `user_table`(`email`, `password`) VALUES ('sample@aaa' , '1111')

dashboard.phpの作成
dashboard.phpは次回で詳細に作成していきます。今回はdashboard.phpだとわかるように、簡単なHTMLを作成しましょう。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ダッシュボード</title>
<meta name="viewport" content="width=1000">
<meta name="robots" content="noindex,nofollow">
<link rel="stylesheet" type="text/css" href="../css/style.css">
</head>
<body>
<section class="wrap">
<h1>ダッシュボード</h1>
</section>
</body>
</html>
これを実際に出力すると、下図のようになります。


dashboard.phpの準備できたら、下記のようにadminフォルダを作成し、その中に配置してください。
hura_come
├── admin
│ └── dashboard.php
├── css
│ └── style.css
├── db_info
│ └── db_info.php
└── save_comment.php
では、本題のlogin.phpを作っていきましょう!
login.phpの作成
全体のコード
login.phpを、実際にブラウザで出力するとこのようになります。

メールアドレスとパスワードを入力してログインボタンを押すと、入力された値をuser_tableテーブルのユーザー情報と照らし合わせます。合致したらdashboard.phpへリダイレクトします。

<?php
session_start();
require '../db_info/db_info.php';
if($_SERVER['REQUEST_METHOD'] === 'POST'){
//メッセージの初期化
$error = '';
//入力値のチェック
if(empty($_POST['email']) || empty($_POST['password'])){
$error = '未入力の項目があります。';
} elseif(strlen($_POST['email']) > 100 || strlen($_POST['password']) > 16){
$error = 'メールアドレスは100文字以内、パスワードは15文字以内でご入力ください。';
} else {
$email = htmlspecialchars($_POST['email'],ENT_QUOTES, 'UTF-8');
$password = htmlspecialchars($_POST['password'],ENT_QUOTES, 'UTF-8');
try{
//データベースへ接続
$dbh = new PDO(
'mysql:host=' . $host . '; dbname=' . $db_name .'; charset=utf8',
$user,
$pass,
array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
)
);
//メールアドレスとパスワードからid番号を取得
$sql = 'SELECT id FROM user_table WHERE email=? AND password=?';
$data[] = $email;
$data[] = $password;
$stmt = $dbh->prepare($sql);
$stmt->execute($data);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if($row == false){
//メールアドレスとパスワードが合致したデータがない場合
echo '<div class="server_error">メールアドレスまたはパスワードが間違っています。</div>';
} else {
//合致したデータが存在する場合
$_SESSION['id']=$row['id'];
$_SESSION['email']=$email;
header('Location: dashboard.php');
exit();
}
//接続解除
$dbh = null;
} catch(PDOException $e){
echo '<div class="server_error">現在サーバーエラーが発生しています。</div>';
}
}
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ログインページ</title>
<meta name="viewport" content="width=1000">
<meta name="robots" content="noindex,nofollow">
<link rel="stylesheet" type="text/css" href="../css/style.css">
</head>
<body>
<section class="wrap login">
<div class="login_wrap">
<img src="../images/logo.jpg" class="ic logo">
<?php
if(isset($error)){
echo '<ul class="error"><li>' . $error . '</li></ul>';
}
?>
<form action="login.php" method="post" class="login_form">
<label>メールアドレス</label>
<input type="email" name="email">
<label>パスワード</label>
<input type="password" name="password">
<input type="submit" name="submit" value="ログイン">
</form>
<center><a href="signup.php">アカウントをお持ちでない方はこちら</a></center>
</div>
</section>
</body>
</html>
login.phpは下記のように配置してください。
hura_come
├── admin
│ ├── dashboard.php
│ └── login.php
├── css
│ └── style.css
├── db_info
│ └── db_info.php
└── save_comment.php
ではコードを細分化して見ていきましょう。
HTMLの用意
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ログインページ</title>
<meta name="viewport" content="width=1000">
<meta name="robots" content="noindex,nofollow">
<link rel="stylesheet" type="text/css" href="../css/style.css">
</head>
<body>
<section class="wrap login">
<div class="login_wrap">
<img src="../images/logo.jpg" class="ic logo">
<?php
if(isset($error)){
echo '<ul class="error"><li>' . $error . '</li></ul>';
}
?>
<form action="login.php" method="post" class="login_form">
<label>メールアドレス</label>
<input type="email" name="email">
<label>パスワード</label>
<input type="password" name="password">
<input type="submit" name="submit" value="ログイン">
</form>
<center><a href="signup.php">アカウントをお持ちでない方はこちら</a></center>
</div>
</section>
</body>
</html>
まずはHTML部分を見ていきましょう。
色々書いていますが、重要なのはform部分です。
<form action="login.php" method="post" class="login_form">
<label>メールアドレス</label>
<input type="email" name="email">
<label>パスワード</label>
<input type="password" name="password">
<input type="submit" name="submit" value="ログイン">
</form>
同一ファイル内で処理を行うので、データの受け渡し先はlogin.phpです。method属性にはpostを指定しましょう。
メールアドレス入力欄にはemail、パスワード入力欄にはpasswordと、name属性を与えます。
また、前回のsave_comment.phpで見たPHPコードが埋め込まれているのがわかりますね。
<?php
if(isset($error)){
echo '<ul class="error"><li>' . $error . '</li></ul>';
}
?>
login.phpでも入力値のチェックを行うので、入力ミスがあればここにエラーメッセージが表示されます。

セッションの開始
ここで1行目に戻ります。
session_start();
最初にセッションの開始を宣言します。

- セッションって?
- サーバ側に一時的にデータを保存する仕組み
- ログイン情報などを扱う際に重要な役割を果たす
db_info.phpの呼び出しと入力値のチェック
require '../db_info/db_info.php';
if($_SERVER['REQUEST_METHOD'] === 'POST'){
//メッセージの初期化
$error = '';
//入力値のチェック
if(empty($_POST['email']) || empty($_POST['password'])){
$error = '未入力の項目があります。';
} elseif(strlen($_POST['email']) > 100 || strlen($_POST['password']) > 16){
$error = 'メールアドレスは100文字以内、パスワードは15文字以内でご入力ください。';
} else {
$email = htmlspecialchars($_POST['email'],ENT_QUOTES, 'UTF-8');
$password = htmlspecialchars($_POST['password'],ENT_QUOTES, 'UTF-8');

- このコードでやっていること
- require文で、データベース情報を記載しているdb_info.phpを呼び出し
- ログインボタンが押されたら処理を実行開始
- エラーメッセージの初期化
- 入力値に問題があればエラーメッセージを表示させる
- 問題がなければ入力した値をエスケープ処理し、変数に格納
データベースへ接続
try{
//データベースへ接続
$dbh = new PDO(
'mysql:host=' . $host . '; dbname=' . $db_name .'; charset=utf8',
$user,
$pass,
array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
)
);
//中略
} catch(PDOException $e){
echo '<div class="server_error">現在サーバーエラーが発生しています。</div>';
}
入力した値に問題がなければ、データベースに接続します。
データベースに接続する場合はtry~catch文を使って例外処理を書きましょう。
テーブルからデータを取得
$sql = 'SELECT id FROM user_table WHERE email=? AND password=?';
$data[] = $email;
$data[] = $password;
$stmt = $dbh->prepare($sql);
$stmt->execute($data);
入力したメールアドレスとパスワードを使って、id番号を取得します。

ユーザー情報があればdashboard.phpへリダイレクト
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if($row == false){
//メールアドレスとパスワードが合致したデータがない場合
echo '<div class="server_error">メールアドレスまたはパスワードが間違っています。</div>';
} else {
//合致したデータが存在する場合
$_SESSION['id']=$row['id'];
$_SESSION['email']=$email;
header('Location: dashboard.php');
exit();
}
$stmt->fetch(PDO::FETCH_ASSOC)の部分で、SQL実行結果を連想配列として取得し、変数rowに格納します。

実行結果がfalse、つまり入力したメールアドレス・パスワードを持つデータがない場合、「メールアドレスまたはパスワードが間違っています」とエラーを表示させます。
逆に入力したメールアドレス・パスワードを持つデータが存在した場合、そのデータのidとメールアドレスをセッションのスーパーグローバル変数に保存します。そしてdashboard.phpにリダイレクトし、処理を終了させます。
以上でlogin.phpの作成は完了です。
dashboard.phpの修正
なぜ修正する必要があるのか?
login.phpができたら、dashboard.phpを少し修正します。


せっかくログイン画面を作っているのに、これじゃセキュリティが意味をなしません。
そこで、ログイン認証されていないユーザーが、直接URLを指定してdashboard.phpにアクセスしようとしたら、エラーが発生するようにします。ここで活躍するのがセッションです。
login.phpのこのコードを見てください。
$_SESSION['id']=$row['id'];
$_SESSION['email']=$email;
ログイン画面でログイン認証した場合だけ、セッションのスーパーグローバル変数が定義されています。つまり、無事にログインした場合に限り、そのユーザーのidとemailのデータがサーバーに保存されるのです。
dashboard.phpへの不正アクセスを防ぐために、$_SESSION[‘id’]を持たないユーザーのアクセスを禁止してしまえばいいのです。
dashboard.phpにコードを追加

<?php
session_start();
session_regenerate_id(true);
//エラー処理
if(!isset($_SESSION['id'])){
header('Location:login.php');
exit();
} else {
echo '<div class="top_bar"><p>こんにちは! ' . $_SESSION['email'] .'さん <a href="logout.php" class="logout_button">ログアウト</a></p></div>';
}
?>
このコードを追加することで、ログイン認証を介していないユーザーのアクセスを防ぐことができます。
では細かく見ていきましょう。
セッションの開始
session_start();
session_regenerate_id(true);
セッションを開始し、セッションIDを新しいものと置き換えます。
- セッションIDって?
- セッションIDとは、アクセスするユーザーを識別するための識別情報
- セッションIDは、セッションが開始されると自動的に発行される
- session_regenerate_id関数で、新しいセッションIDを発行して置き換えられる
- セッションIDを新しいものに置き換えるのは、セッションIDの特定されにくくして、セッションハイジャック(なりすましなど)を防ぐため
- セッションIDを新しくしても、定義したスーパーグローバル変数の値は変わらない
不正アクセスを弾く
if(!isset($_SESSION['id'])){
header('Location:login.php');
exit();
} else {
echo '<div class="top_bar"><p>こんにちは! ' . $_SESSION['email'] .'さん <a href="logout.php" class="logout_button">ログアウト</a></p></div>';
}
if文を使って、アクセスを許可するか否か判別します。
$_SESSION[‘id’]に値が存在しない、つまりログイン画面を介していないユーザーにはlogin.phpに強制的にリダイレクトしてもらいます。
きちんとログイン認証してアクセスしてきたユーザーには「こんにちは! ○○さん」と表示して、アクセスを歓迎してあげましょう!
logout.phpの作成
全体のコード
これで不正アクセスを防ぐことができますが、ちゃんと機能しているかログアウトして確認してみましょう。
では、最後にログアウトするためのlogout.phpを作っていきましょう!
<?php
session_start();
$_SESSION = array();
if(isset($_COOKIE[session_name()]) == true){
setcookie(session_name() , '' ,time()-42000,'/');
}
session_destroy();
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ログアウトしました</title>
<meta name="viewport" content="width=1000">
<meta name="robots" content="noindex,nofollow">
<link rel="stylesheet" type="text/css" href="../css/style.css">
</head>
<body>
<section class="wrap">
<h1>ログアウトしました。</h1>
<p><a href="login.php">ログインページに戻る</a></p>
</section>
</body>
</html>
logout.phpを準備できたら、下記のように配置してください。
hura_come
├── admin
│ ├── dashboard.php
│ ├── login.php
│ └── logout.php
├── css
│ └── style.css
├── db_info
│ └── db_info.php
└── save_comment.php
ここで注目するのはPHPの部分だけです。では見ていきましょう。
ログアウトの仕組み
ログアウトするための方法は、セッションを削除することです。
<?php
session_start();
$_SESSION = array();
if(isset($_COOKIE[session_name()]) == true){
setcookie(session_name() , '' ,time()-42000,'/');
}
session_destroy();
?>
セッションの削除はほぼ定型文のようなものです。上記の方法で完全にセッションを削除できます。

実際にログインしてみよう!
作成したら、まずは挙動確認! 実際にログインできるか確かめてみよう。


上手く動作しましたか?
上手くいかない場合はどこか間違っている箇所がないか、よく確認してみましょう。
まとめ
今回制作したのは、dashboard.phpとlogin.phpとlogout.phpです。
ここまで制作したら、下記のようなツリー構造になっていると思います。
hura_come
├── admin
│ ├── dashboard.php
│ ├── login.php
│ └── logout.php
├── css
│ └── style.css
├── db_info
│ └── db_info.php
└── save_comment.php
