こんにちは、MIO webデザインです。
さて、唐突ですがWordPressって便利ですよね。サイト運営が簡単に行えて、プラグインを使えば機能を拡張できるというのも素晴らしい。ブログ機能もあり、訪問者がコメントを投稿できるというのもグッド。今やWordPressは市場の6割近くを占めるCMSとなりました。
そこでふと思ったのですが、WordPressのようなコメント機能を作ってみたい!

コメントを受け付けたら管理画面で承認したり、削除したり、返信もできたら最高ですね。
と、いうわけで今回から数回に分けて『WordPressのようなコメント管理システムを作ってみよう』と思います!
- 対象者
- PHPの基礎がわかる人
- phpMyAdminの使い方がわかる人
これから作っていくもの
改めまして今回から数回に分けて、MIO webデザインのマスコットキャラクターから名前を取り、簡易コメント管理システム『ふらこめ(necofly comment system)』なるものを作っていこうと思います。
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
では早速作っていきましょう!
今回作るもの – 『コメント投稿機能』

今回作っていくのは『コメント機能』です。
フォームにコメントを入力して送信ボタンを押すと、入力した値をデータベースに保存するプログラムです。
第1回目ということで、データベースの作成から見ていきましょう。
phpMyAdminでデータベースとテーブルの準備

まずはphpMyAdminにログインして、hurakomeデータベースを作ります。

hurakomeデータベースが作成できたら、次に、投稿されたコメントを格納するcom_tableテーブルを作成します。必要なカラムは6つ。下記の画像を参考に6つのカラムを作成してください。idにAUTO_INCREMENTの設定をするのをお忘れなく!

手動で作成する以外にも、下記のコードを『SQL』に貼り付けて作成することもできます!
CREATE TABLE IF NOT EXISTS `com_table` (
`id` int(255) NOT NULL,
`comment` varchar(1000) COLLATE utf8_unicode_ci DEFAULT NULL,
`name` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL,
`email` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`display` tinyint(1) DEFAULT NULL,
`reply` varchar(1000) COLLATE utf8_unicode_ci DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `com_table`
ADD PRIMARY KEY (`id`);
ALTER TABLE `com_table`
MODIFY `id` int(255) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=7;

phpMyAdminの操作はこれで終了。これから実際にプログラムを書いていきましょう!
db_info.phpの作成
全体のコード
今回のプログラムではデータベースへアクセスすることになるので、プログラムを書き始める前に、接続に必要な情報をこのファイルにまとめておきます。
<?php
$host = 'localhost';
$user = 'root';
$pass = 'root';
$db_name = 'hurakome';

データベース接続時に必要になるのが『ホスト名』『ユーザー名』『パスワード』『データベース名』の4つです。
プログラムを設置する環境によって、これらの情報は変わってしまうので、最初に専用のファイルを準備して変数に格納してしまいましょう。もし環境が変わったとしても、このファイルを修正するだけでいいので管理が非常に楽になります。
ファイルの配置

hura_come
└── db_info
└── db_info.php
db_info.phpの作成はこれで終了です!
save_comment.phpの作成
全体のコード
save_comment.phpを、実際にブラウザで出力するとこのようになります。

コメント・お名前・メールアドレスに必要事項を記入して投稿ボタンを押すと、入力した内容がhurakomeデータベースのcom_tableテーブルに保存されます。

<?php
require 'db_info/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>';
}
//コメントが入力されたら
if($_SERVER['REQUEST_METHOD'] === 'POST'){
//メッセージの初期化
$error = '';
$success = '';
//入力値のチェック
if(empty($_POST['comment']) || empty($_POST['name']) || empty($_POST['email'])){
$error = '入力されていない項目があります。';
} elseif(strlen($_POST['comment']) > 1000){
$error = 'コメントは1000文字以内でご記入ください。';
} elseif(strlen($_POST['name']) > 15){
$error = 'お名前は15文字以内でご入力ください。';
} elseif(strlen($_POST['email']) > 100){
$error = 'メールアドレスは100文字以内でご入力ください。';
} else {
$comment = htmlspecialchars( $_POST['comment'] ,ENT_QUOTES, 'UTF-8');
$name = htmlspecialchars( $_POST['name'] ,ENT_QUOTES, 'UTF-8');
$email = htmlspecialchars( $_POST['email'] ,ENT_QUOTES, 'UTF-8');
try{
//SQL操作
$sql = 'INSERT INTO com_table(comment,name,email) VALUE (?,?,?)';
$data[] = $comment;
$data[] = $name;
$data[] = $email;
$stmt = $dbh->prepare($sql);
$stmt->execute($data);
//接続解除
$dbh = null;
$success = 'コメントを投稿しました。承認をお待ちください。';
}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 href="https://use.fontawesome.com/releases/v5.0.6/css/all.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<section class="wrap ww">
<img src="images/logo.jpg" class="ic">
<?php
if(isset($error)){
echo '<ul class="error"><li>' . $error . '</li></ul>';
}
if(isset($success)){
echo '<ul class="success"><li>' . $success . '</li></ul>';
}
?>
<form action="save_comment.php" method="post" class="comment_form">
<label>コメント</label>
<textarea name="comment"></textarea>
<label>お名前</label>
<input type="text" name="name">
<label>メールアドレス</label>
<input type="email" name="email">
<input type="submit" name="submit" value="投稿">
</form>
</section>
</body>
</html>
save_comment.phpは下記のように配置してください。
hura_come
├── 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 href="https://use.fontawesome.com/releases/v5.0.6/css/all.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<section class="wrap ww">
<img src="images/logo.jpg" class="ic">
<?php
if(isset($error)){
echo '<ul class="error"><li>' . $error . '</li></ul>';
}
if(isset($success)){
echo '<ul class="success"><li>' . $success . '</li></ul>';
}
?>
<form action="save_comment.php" method="post" class="comment_form">
<label>コメント</label>
<textarea name="comment"></textarea>
<label>お名前</label>
<input type="text" name="name">
<label>メールアドレス</label>
<input type="email" name="email">
<input type="submit" name="submit" value="投稿">
</form>
</section>
</body>
</html>
まずはHTMLを準備します。
色々書いていますが、重要なのはform部分です。
<form action="save_comment.php" method="post" class="comment_form">
<label>コメント</label>
<textarea name="comment"></textarea>
<label>お名前</label>
<input type="text" name="name">
<label>メールアドレス</label>
<input type="email" name="email">
<input type="submit" name="submit" value="投稿">
</form>
同一ファイル内で処理を行うので、データの受け渡し先はsave_comment.phpです。method属性にはpostを指定しましょう。
コメント入力欄にはcomment、名前の入力欄にはname、メールアドレスの入力欄にはemailと、name属性を与えます。
db_info.phpの呼び出し

require 'db_info/db_info.php';
データベースに接続するためには、先ほど作成したdb_info.phpを呼び出す必要があります。
ここではrequireを使って呼び出しています。

データベースへの接続
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文を使って、例外処理も定義しておきましょう。
ここではPODクラスを使用してデータベースへ接続しています。よく見るとdb_info.phpで定義した変数がありますね。ホスト名・データベース名・ユーザー名・パスワードは、このようにデータベースに接続する時に使われます。

投稿ボタンが押されたら処理を開始
if($_SERVER['REQUEST_METHOD'] === 'POST'){
//メッセージの初期化
$error = '';
$success = '';
if文を使い、POSTでデータが送られてきたら(つまりフォームのボタンが押されたら)処理を実行します。
まずは$errorと$successの2つの変数を準備します。

入力された値をチェック
if(empty($_POST['comment']) || empty($_POST['name']) || empty($_POST['email'])){
$error = '入力されていない項目があります。';
} elseif(strlen($_POST['comment']) > 1000){
$error = 'コメントは1000文字以内でご記入ください。';
} elseif(strlen($_POST['name']) > 15){
$error = 'お名前は15文字以内でご入力ください。';
} elseif(strlen($_POST['email']) > 100){
$error = 'メールアドレスは100文字以内でご入力ください。';
} else {
$comment = htmlspecialchars( $_POST['comment'] ,ENT_QUOTES, 'UTF-8');
$name = htmlspecialchars( $_POST['name'] ,ENT_QUOTES, 'UTF-8');
$email = htmlspecialchars( $_POST['email'] ,ENT_QUOTES, 'UTF-8');
投稿ボタンが押されたからといって、何でもかんでもデータベースに保存するわけにはいきません。
例えば、フォームに何も記述しないまま投稿ボタンを押してしまったら、NULLがデータベースに保存されてしまいます。
なので、入力された値がデータベースに保存していいものかどうか、まずはチェックしなければなりません。
- 入力値のチェック
- コメント・名前・メースアドレスのどれか1つでも未入力のものがあればエラーメッセージを表示
- コメントが1000文字を超えたらエラー処理
- 名前が15文字を超えたらエラー処理
- メースアドレスが100文字以上ならエラー処理

<?php
if(isset($error)){
echo '<ul class="error"><li>' . $error . '</li></ul>';
}
if(isset($success)){
echo '<ul class="success"><li>' . $success . '</li></ul>';
}
?>
HTMLの中に上記のPHPが埋め込まれています。
これは「もし変数errorに何かしらの値があれば、変数errorを出力する」「もし変数successに何かしらの値があれば、変数successを出力する」というものです。入力値に誤りがあれば、それに対応したエラーメッセージがここに表示されます。

そして上記の条件に当てはまらなかった、つまりエラーが発生しなかった場合は、入力された値をhtmlspecialcharsでエスケープ処理し、それぞれ変数に格納します。
SQL文でデータを保存
try{
//SQL操作
$sql = 'INSERT INTO com_table(comment,name,email) VALUE (?,?,?)';
$data[] = $comment;
$data[] = $name;
$data[] = $email;
$stmt = $dbh->prepare($sql);
$stmt->execute($data);
//接続解除
$dbh = null;
$success = 'コメントを投稿しました。承認をお待ちください。';
}catch(PDOException $e){
echo '<div class="server_error">現在サーバーエラーが発生しています。</div>';
}
入力した値に問題がなければ、SQL文を使ってデータを保存します。この時もtry~catch文を使って、例外処理も定義しておきましょう。

INSERTで各種データを追加できたら、$successにメッセージを代入して、処理は終了です。
$successに値が入ったため、変数errorのように成功メッセージが表示されます。

以上でsave_comment.phpの作成は完了です。
スタイルシートで外観を調整
おまけですが、外観の見栄えをよくするために、CSSのコードも貼り付けておきます(スタイルの解説は割愛)。
よければお使いください。
@charset "UTF-8";
html,
body {
margin: 0;
padding: 0;
-webkit-text-size-adjust: 100%;
font-family: apple-system, BlinkMacSystemFont, "Helvetica Neue", "Segoe UI", "Noto Sans Japanese", "ヒラギノ角ゴ ProN W3", Meiryo, sans-serif;
}
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
overflow-x: hidden;
background: #5433FF;
background: -webkit-linear-gradient(to right, #A5FECB, #20BDFF, #5433FF);
background: linear-gradient(to right, #A5FECB, #20BDFF, #5433FF);
}
body::-webkit-scrollbar {
display: none;
}
p {
font-size: 18px;
line-height: 1.5;
font-family: apple-system, BlinkMacSystemFont, "Helvetica Neue", "Segoe UI", "Noto Sans Japanese", "ヒラギノ角ゴ ProN W3", Meiryo, sans-serif;
color: #333;
}
img {
max-width: 100%;
height: auto;
}
a {
outline: none;
text-decoration: none;
}
ul{
list-style-type: none;
padding: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
input,
textarea {
display: block;
margin: auto;
}
.wrap {
width: 950px;
margin: auto;
padding: 30px 0;
position: relative;
}
.login{
height: 100vh;
padding: 0;
}
.ww {
background: #fff;
}
.ic {
display: block;
margin: auto;
}
/* comment_form
******************************************************************************/
.comment_form {
width: 80%;
margin: 50px auto;
}
.comment_form input[type="text"],
.comment_form input[type="email"],
.comment_form textarea {
width: 90%;
background: #eeeeee;
font-size: 16px;
border: solid 1px #999;
border-radius: 5px;
padding: 2%;
color: #333;
font-weight: bold;
}
.comment_form textarea {
height: 100px;
}
.comment_form label {
display: block;
width: 92%;
margin: 20px auto 5px;
padding: 0;
font-weight: bold;
color: #333;
font-size: 14px;
}
.comment_form input[type="submit"] {
background: #5433FF;
background: -webkit-linear-gradient(to right, #cea5fe, #5433FF);
background: linear-gradient(to right, #cea5fe, #5433FF);
color: #fff;
font-size: 18px;
margin: 20px auto;
padding: 5px 10px;
width: 100px;
border-radius: 50px;
font-weight: 900;
}
.comment_form input[type="submit"]:hover {
opacity: 0.8;
}
/*error*/
.error li {
width: 75%;
margin: 20px auto;
color: #ff0d4b;
font-weight: bold;
}
.server_error {
background: #000;
padding: 20px 0;
text-align: center;
font-size: 20px;
color: #ffff00;
font-weight: 900;
}
/*success*/
.success li {
width: 75%;
margin: 20px auto;
color: #4e0dff;
font-weight: bold;
}
/* comment list
******************************************************************************/
h2{
font-size: 22px;
text-align: center;
color: #333;
position: relative;
padding: 10px 0;
}
h2:after{
content: "";
display: block;
width: 70px;
height: 3px;
border-radius: 50px;
position: absolute;
bottom: 0;
left: 0;
right: 0;
margin: auto;
background: #333;
}
.comment_list{
width: 90%;
margin: auto;
}
.comment_list li{
padding: 10px;
font-size: 16px;
color: #333;
}
.comment_list li:nth-child(even){
background: #eee;
}
.comment_list .name{
margin: 10px;
font-size: 12px;
font-style: italic;
color: #888;
}
.comment_list li > .reply{
padding: 10px 20px 10px 10px;
}
.comment_list li > .reply li::before {
font-family: "Font Awesome 5 Free";
content: "\f3e5";
display: inline-block;
line-height: 1;
font-weight: bold;
margin-right: 10px;
}
/* sign up ・ Login
******************************************************************************/
.logo {
width: 40%;
}
.login_wrap {
width: 70%;
margin: auto;
background: #fff;
padding: 5% 0%;
position: absolute;
top: 50%;
left: 50%;
transform: translateY(-50%) translateX(-50%);
-webkit- transform: translateY(-50%) translateX(-50%);
border-radius: 8px;
}
.login_form {
width: 85%;
margin: 0 auto;
}
.login_form input[type="email"],
.login_form input[type="password"] {
width: 70%;
font-size: 18px;
color: #666;
font-weight: bolder;
padding: 2% 5%;
border: solid 1px #999;
background: #eeeeee;
border-radius: 50px;
}
.login_form label {
text-align: center;
display: block;
margin: 20px 0 5px;
font-weight: bold;
color: #999;
}
.login_form input[type="submit"] {
background: #5433FF;
background: -webkit-linear-gradient(to right, #cea5fe, #5433FF);
background: linear-gradient(to right, #cea5fe, #5433FF);
color: #fff;
font-size: 18px;
margin: 20px auto;
padding: 5px 10px;
width: 100px;
border-radius: 50px;
font-weight: 900;
}
.login_form input[type="submit"]:hover {
opacity: 0.8;
}
/* dashboard
******************************************************************************/
.top_bar{
background: #1a1a1a;
padding: 10px 20px 10px;
}
.top_bar p{
color: #999;
font-size: 16px;
text-align: right;
}
.logout_button{
display: inline-block;
color: #ccc;
border: solid 1px #ccc;
padding: 5px;
font-size: 14px;
transition: all 0.5s;
}
.logout_button:hover{
opacity: 0.5;
}
/*table*/
.db_table{
width: 100%;
margin: auto;
background: #fff;
word-wrap: break-word
}
.db_table thead th{
background: #333;
color: #ccc;
font-size: 18px;
padding: 1%;
border: solid 1px #777;
}
.db_table thead th:nth-child(1),
.db_table thead th:nth-child(3),
.db_table thead th:nth-child(4){
width: 20%;
}
.db_table thead th:nth-child(2){
width: 40%;
}
.db_table tbody td{
padding: 1%;
border: 1px solid #ccc;
font-size: 14px;
color: #333;
}
.db_table tbody tr:nth-child(even){
background: #eee;
}
/*button*/
.go_home{
display: block;
text-align: center;
}
style.cssを準備できたら、下記のように配置してください。
hura_come
├── css
│ └── style.css
├── db_info
│ └── db_info.php
└── save_comment.php
実際にコメントを投稿してみよう



今回入力したコメント・名前・メールアドレスはcom_tableテーブルのcomment・name・emailカラムに保存されるのがわかりますね。
コメント投稿フォームで入力した値は、com_tableテーブルのcomment・name・emailカラムに保存されます。idはAUTO_INCREMENTにチェックを入れたので、自動的に番号が割り振られています。
まとめ
今回制作したのは、db_info.phpとsave_comment.phpです。
style.cssもおまけで掲載していますので、よければ使ってください。
ここまで制作したら、下記のようなツリー構造になっていると思います。
hura_come
├── css
│ └── style.css
├── db_info
│ └── db_info.php
└── save_comment.php
