PHPで掲示板サイトを作ってみよう【初心者向け】

こちらは、これからプログラミングを学んでいきたいという初心者の方向けの記事です。

一緒にPHPで掲示板サイトを作成し、理解を深めてもらえればと思います。

学べる技術

こちらの記事で学べる技術は、

言語:PHP

DB(データベース):Mysql

です。

環境は、「xampp」を使用し、構築します。

今回の完成イメージは以下のような感じです。

投稿ページ投稿完了ページを行ききし、投稿ページ側に投稿内容が表示されるような仕組みを作成します。

2ページに分けた理由は、登録の処理取得の処理を分けて理解してもらうためです。

css(デザイン)がついていない分、見た目がかなり地味ですが、動作部分のコードにのみ着目して欲しいため、あえてつけていません。

また、上記のようなものを作成後、演習課題を用意しています。

難易度はそれほど高くないため、挑戦してみましょう。

xamppとは

読み方は、「ザンプ」と読みます。

XAMPPは以下の文字から構成されている。

  • X - Windows、Linux、macOS、Solarisのクロスプラットフォーム
  • A - ApacheのA
  • M - MariaDB(旧バージョンはMySQL)のM
  • P - PHPのP
  • P - PerlのP

元々は対応OSLinuxのみであり、その頭文字Lを付けLAMPPと称したが、後に複数のOSに対応したためLをXに変えXAMPPとなった。

(wikipediaより引用)

これらのWEBアプリケーションの開発環境となるソフトウェアを一括でダウンロードできるため、環境構築が容易に行えます。

xamppのインストール

https://www.apachefriends.org/jp/index.html

上記のサイトにアクセスします。

私は、Windowsで環境を作成するため、「Windows向けXAMPP」を選択します。

(選択すると、自動でダウンロードされます)

ダウンロードした「xampp-windows-x64-7.4.1-0-VC15-installer.exe」を実行し、PCにインストールします。

インストールが完了したら、Cドライブの下にxamppフォルダが作成されていると思います。

その中にある「xampp-control.exe」を起動してください。

上記の画面が表示されたら、インストールの完了です。

XAMPPを起動する

xampp-control.exe」を起動し、xamppコントロールパネルを表示します。

この中で「Apache」と「MySQL」を使用します。

Startを押下し、起動させます。

起動すると、「Admin」というボタンが活性状態になりました。

まずは、ApacheのAdminボタンを押下してみます。

すると、「localhost」というurlのページが開かれます。

これは、「C:\xampp\htdocs\index.php」の内容が表示されています。

index.phpファイルをテキストエディタで開き、以下の内容を入力します。

(エディタの導入方法などは、説明しませんが、エディタを入れておくことで、自動で入力補完をしてくれたり、見やすく色づけをしてくれるため、導入しておくと、良いです。

また、テキストエディタで編集をすると、BOMというものがついてしまうため、そのまま編集するのはお勧めできません。

私は、VScodeというエディタを使用しています。)

<?php
echo 'Hellow world!!';
?>

もう一度、「localhost」へアクセスします。

すると、先ほど入力した「Hello world!!」という文字が表示されると思います。

次は、xamppコントロールパネルからMySQLのAdmimボタンを押下してみます。

すると、「http://localhost/phpmyadmin/」というurlのページにアクセスされ、上記のようなページが表示されると思います。

こちらからは、DB内の操作をGUIで簡単に行うことができます。

しかし、基本的に今回はここからは操作しません。

DBを作成する

まずは、DBを作成します。

phpMyAdminから作成しても良いのですが、練習のためコンソールからCUIで作成します。

xamppコントロールパネルの右側にある「Shell」というボタンを押下します。

すると、上記のような画面が表示されます。

まずは、MySQLにログインします。

初期状態では、

ユーザ名: root

パスワード:なし

の状態のユーザが存在しますので、こちらのユーザを使用します。

以下のコマンドを実行してください。

mysql -u root -p

Enter password: と聞かれますが、何も入力せず、Enterを押します。

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 23
Server version: 10.4.10-MariaDB mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>

と表示されたら、ログインが完了しました。

次は、以下を入力して下さい。

show databases;

こちらは、MySQLの中に作成されたDB一覧を表示するコマンドです。

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| phpmyadmin         |
| test               |
+--------------------+
5 rows in set (0.001 sec)

初期状態では、上記のような表示のはずです。

新たに、「sample」という名前のDBを作成します。

create database sample character set utf8;

DBが作成されました。

Query OK, 1 row affected (0.005 sec)

問題がなければ、上記の表示です。

作成されたか、確認をします。

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| phpmyadmin         |
| sample             |
| test               |
+--------------------+
6 rows in set (0.001 sec)

無事作成されていますね。

次に、使用するデータベースを選択します。

先ほど作成した「sample」DBを選択します。

以下を入力してください。

use sample;

入力後、noneとなっていた部分が、sampleに変化しました。

これで使用するDBが選択済みの状態となりました。

MariaDB [(none)]> use sample
Database changed
MariaDB [sample]>

次にDB内に存在するtableを確認します。

以下を入力してください。

show tables;

まだ、なにも作成していないため、

Empty set (0.001 sec)

と表示されます。

最後にテーブルを作成します。

以下を入力してください。(コピペで大丈夫です)

CREATE TABLE `post` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '投稿番号',
  `name` varchar(100) COLLATE utf8_unicode_ci NOT NULL COMMENT '投稿者名',
  `contents` varchar(100) COLLATE utf8_unicode_ci NOT NULL COMMENT '投稿内容',
  `created_at` datetime DEFAULT NULL COMMENT '登録日時',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT = '投稿情報';

問題なく、実行され、テーブルが登録されました。

Query OK, 0 rows affected (0.038 sec)

これで準備完了です。

投稿処理を記述する

まずは、トップページの見た目だけ、作成していきます。

C:\xampp\htdocs\index.php」の内容を編集し、以下を記述します。


<!DOCTYPE html>
<meta charset="UTF-8">
<title>掲示板サンプル</title>
<h1>掲示板サンプル</h1>
<section>
    <h2>新規投稿</h2>
    <form action="send.php" method="post">
        名前 : <input type="text" name="name" value=""><br>
        投稿内容: <input type="text" name="contents" value=""><br>
        <button type="submit">投稿</button>
    </form>
</section>

そして、「localhost」というurlにアクセスしてみましょう。

このような画面が表示されていると思います。

次に、「C:\xampp\htdocs」の中に「send.php」というファイルを作成し、以下を書き込みます。

<!DOCTYPE html>
<meta charset="UTF-8">
<title>掲示板サンプル</title>
<h1>掲示板サンプル</h1>
<section>
    <h2>投稿完了</h2>
    <button onclick="location.href='index.php'">戻る</button>
</section>

これで、もう一度、動作を確認してみます。

すると、

「投稿」ボタンを押すと、投稿完了画面へ遷移

「戻る」ボタンを押すと、投稿画面へ遷移

という動作を確認することができます。

次にDBへ情報を登録するために以下をsend.phpに記述します。

<!DOCTYPE html>
<meta charset="UTF-8">
<title>掲示板サンプル</title>
<h1>掲示板サンプル</h1>
<section>
    <h2>投稿完了</h2>
    <button onclick="location.href='index.php'">戻る</button>
</section>
 
<!-- 追記ここから -->
<?php
$id = null;
$name = $_POST["name"];
$contents = $_POST["contents"];
date_default_timezone_set('Asia/Tokyo');
$created_at = date("Y-m-d H:i:s");
//DB接続情報を設定します。
$pdo = new PDO(
    "mysql:dbname=sample;host=localhost","root","",array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET `utf8`")
);
//ここで「DB接続NG」だった場合、接続情報に誤りがあります。
if ($pdo) {
    echo "DB接続OK";
} else {
    echo "DB接続NG";
}
//SQLを実行。
$regist = $pdo->prepare("INSERT INTO post(id, name, contents, created_at) VALUES (:id,:name,:contents,:created_at)");
$regist->bindParam(":id", $id);
$regist->bindParam(":name", $name);
$regist->bindParam(":contents", $contents);
$regist->bindParam(":created_at", $day);
$regist->execute();
//ここで「登録失敗」だった場合、SQL文に誤りがあります。
if ($regist) {
    echo "登録成功";
} else {
    echo "登録失敗";
}
?>
<!-- 追記ここまで -->

少し、難しくなりましたね。

先ほどまでは、HTMLのみでの記述でしたが、ここからPHPが登場します。

ここまでで、投稿内容がDBに登録される流れが完成しました。

もう一度動かしてみましょう。

ただ、このままだと、投稿内容はまだ表示されていないです。

確認するためには、DBから直接確認を行います。

コンソールからMySQLにログインし、DB選択後、以下を実行します。

select * from post;

postテーブルのすべての値が表示されます。

+----+---------------+---------------+---------------------+
| id | name          | contents      | created_at          |
+----+---------------+---------------+---------------------+
|  1 | 繝・せ繝亥錐      | hello world   | 2020-01-12 07:42:33 |
|  2 | 繝・せ繝亥錐2     | goodbye world | 2020-01-12 07:44:17 |
+----+---------------+---------------+---------------------+

日本語を使用していると、文字化けを起こしていますが、登録は確認できました。

(設定を行うことで文字化けを起こさないようにもできます。

後で設定方法についても記載しています。)

DBから投稿内容を取得する

C:\xampp\htdocs\index.php」に以下を記述します。

<!-- 追記1ここから -->
<?php
//DB接続情報を設定します。
$pdo = new PDO(
    "mysql:dbname=sample;host=localhost","root","",array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET `utf8`")
);
//ここで「DB接続NG」だった場合、接続情報に誤りがあります。
if ($pdo) {
    echo "DB接続OK";
} else {
    echo "DB接続NG";
}
//SQLを実行。
$regist = $pdo->prepare("SELECT * FROM post");
$regist->execute();
//ここで「登録失敗」だった場合、SQL文に誤りがあります。
if ($regist) {
    echo "登録成功";
} else {
    echo "登録失敗";
}
?>
<!-- 追記1ここまで -->

<!DOCTYPE html>
<meta charset="UTF-8">
<title>掲示板サンプル</title>
<h1>掲示板サンプル</h1>
<section>
    <h2>新規投稿</h2>
    <form action="send.php" method="post">
        名前 : <input type="text" name="name" value=""><br>
        投稿内容: <input type="text" name="contents" value=""><br>
        <button type="submit">投稿</button>
    </form>
</section>
 
<!-- 追記2ここから -->
<section>
	<h2>投稿内容一覧</h2>
		<?php foreach($regist as $loop):?>
			<div>No:<?php echo $loop['id']?></div>
			<div>名前:<?php echo $loop['name']?></div>
			<div>投稿内容:<?php echo $loop['contents']?></div>
			<div>------------------------------------------</div>
		<?php endforeach;?>
	
</section>
<!-- 追記2ここまで -->

動作確認をすると、投稿内容を登録し、取得するという流れが完成しました。

これで、掲示板作成は終了です。

コード解説(PHPのみ)

登録部分のコード(send.php記載)を使用し、説明していきます。

処理を順番に見ていきましょう。

<?php

最初に書いてある <?php というのはPHPの記述の開始タグです。

一番後ろについている ?> までがPHPの処理になります。

$id = null;
$name = $_POST["name"];
$contents = $_POST["contents"];
date_default_timezone_set('Asia/Tokyo');
$created_at = date("Y-m-d H:i:s");

フォームから送信された情報は、$_POSTに値が格納されているので、それを取り出し、変数に格納しています。

試しに var_dump($_POST); という一文を追加してみると、どんな値が送信されてきたか確認することができます。

date("Y-m-d H:i:s")という部分では、現在の日時を取得しています。

//DB接続情報を設定します。
$pdo = new PDO(
    "mysql:dbname=sample;host=localhost","root","",array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET `utf8`")
);

ここでは、DBの接続情報を設定しています。

分解してみていきましょう。

dbname=sample

「sample」というデータベースを使用します。

host=localhost

接続先はlocalhostです。

"root",""

ユーザ名「root」、パスワードは設定していません。

array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET `utf8`"

文字コードは、utf8を使用します。

//ここで「DB接続NG」だった場合、接続情報に誤りがあります。
if ($pdo) {
    echo "DB接続OK";
} else {
    echo "DB接続NG";
}

もし、先ほどの接続情報に誤りがあった場合は、「DB接続NG」と表示されます。

こちらは、接続情報に誤りがないかの確認用の処理のため、動作を確認できたら削除してよいです。

$regist = $pdo->prepare("INSERT INTO post(id, name, contents, created_at) VALUES (:id,:name,:contents,:created_at)");
$regist->bindParam(":id", $id);
$regist->bindParam(":name", $name);
$regist->bindParam(":contents", $contents);
$regist->bindParam(":created_at", $day);
$regist->execute();

こちらの処理で、SQLを実行しています。

bindParamというものを使用し、 第一引数の記述 を 第二引数の変数の中身に置き換えています。

そうすることで、変数定義した中身で置き換えられ、ユーザの入力値をDBに登録することができます。

ただ、これかなり面倒な動作をしていますよね。

なんで?って思ったからもいるかもしれませんが、これはSQLインジェクションを起こさないための対策として、必要なことなのです。

//ここで「登録失敗」だった場合、SQL文に誤りがあります。
if ($regist) {
    echo "登録成功";
} else {
    echo "登録失敗";
}

ここも、確認用の処理なので、動作が確認できたら、削除してよいです。

DBの文字化けを修正する

xamppコントロールパネルからMySQLのConfigをクリックし、「my.ini」を選択します。

これは、「C:\xampp\mysql\bin\my.ini」を参照しているようなので、ここから直接編集しても良いです。

ファイルのかなり下の方、160行目付近に

[mysql]
# Remove the next comment character if you are not familiar with SQL
#safe-updates

という記述があるので、その下に

default-character-set = cp932

と書き込み、保存をします。

MySQLを再起動し、コンソールから再度取得すると、文字化けが治っていると思います。

演習課題

課題1

投稿内容一覧に、投稿時間を表示させましょう。

課題2

最新の投稿20件までを新しい順に表示するように書き換えましょう。

(現在は古い順に全件を表示)

課題3

投稿送信時の動作を変更します。

投稿完了ページをなくして、もう一度、投稿ページに遷移するように変更してみましょう。

課題4

現在は、フォームの入力値が空でも送信され、DBに登録されてしまいます。

もし、フォームの入力値が空だった場合、送信できないようにしましょう。

また、上部にエラーメッセージを表示しましょう。

課題5

投稿時にajaxでの処理を実装してみましょう。

(jQuery ajaxで調べると色々出てくるはずです。)

課題6

cssでデザインをつけてみよう。

以下は例なので、これと同じでなくても大丈夫です。

なので、参考程度に利用してください。

演習課題は以上になります。

まだ改善すべき点はあると思いますので、他にも改善してみてください。

また、演習課題の答えについては、別記事で投稿を考えています。

投稿をしましたら、こちらの記事の最下部にリンクを張り付ける予定です。

おすすめの記事