PHPの基本はわかったんだけど
どう応用したらいいのかわからない。
簡単に作れて、スキル向上に繋がるものはないかな?
PHPに限りませんが、プログラミング初心者が入門書を終えた辺りでぶつかる悩みとして「何を作ったらいいのかわからない悩み」というものがあります。
入門書で基本的な文法はわかったんだけど、それをどのように生かしてプログラムを作ればいいのだろう。TwitterやFacebookのようなすごいアプリを作ってみたい夢は有るけど、それを実現するために何を学んでいったらいいのかわからない──
ともすれば、ここで目標を見失って挫折してしまいかねない、入門書を終了した時期というのは非常にデリケートな時期です。そこで今回は入門書を終えたばかりの方でも簡単に作れて、そこそこ学びも得られる掲示板の作り方について見ていきます。
掲示板作成はPHPの応用課題の定番です。この後に続くWebアプリ作成の入口になるような基礎・アイディアの詰まった、なかなか優秀な課題です。
ぜひ一度手を動かして掲示板を作ってみて、実際に動くものが作れた達成感を味わってみてください。
DB不要! 簡単掲示板の作り方
まずはデータベースを利用せず、テキストファイルにデータを保存する形式の掲示板を作ってみたいと思います。
見た目は以下のようなシンプルなものにしましょう。見た目はCSSで調整することができますが本題からそれるので、今回は扱いません。
ベースになるHTMLは以下のようにします。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>testbord</title> </head> <body> <form action="bord.php" method="post"> <div> <label for="name">名前</label> <input type="text" id="name" name="name"> </div> <div> <label for="message">内容</label> <input type="text" id="message" name="message"> </div> <input type="submit" name="send" value="送信する"> </form> <h2>表示欄</h2> <div></div> </body> </html>
これにPHPで動作を追加して、掲示板をつくっていきましょう。
まずは簡単にこれから作り上げる掲示板を設計してみましょう。最初に必要な機能を列挙してみます。
- 1. 内容に書き込んだ文章を名前とセットにして記録する
- 2. 送信するボタンを押すと1. の機能が実行される
- 3. 記録されている内容を表示欄にすべて表示する
他にも書き込んだ日時を一緒に表示したりだとか、ユーザーごとにIDを割り振ったりだとか、入力欄の空白を許さないだとか色々と付加機能は考えられますが、まず最低限1-3までが実装できていれば掲示板といえる物ができあがるでしょう。
まずは最低限動くものを、という考え方は結構大事です。完成までの時間や技術が少なくて済みますし、なにより動くものができ上がるのは単純に嬉しいものです。
実用的なものを組み始めた最初の段階では、いかにして最速で動く段階まで到達できるかを重視しましょう。
次に、必要な技術を選定していきます。
今回は最初に書いたようにデータベースを使わずに、テキストファイルにすべての情報を記録する方向で進めていきます。そのため、HTMLとPHPが動いて、記録用のテキストファイルを用意できる環境であればローカルでもリモートでもなんでもOKです。
……なのですが、このコードは学習用ということでセキュリティに関する対策を一切入れていません。PHPのセキュリティ対策について書き出すとそれだけで数記事分も書けてしまうので、意図的に省略しています。
ですので、このコードを不特定多数がアクセスできるような場所で動かすのは絶対に止めてください。よろしくおねがいします。
データベースを使うと、1つの書き込みに対してIDや記録日時、書き込み内容などが簡単に記録できるうえ、検索も容易なので、本格的な掲示板を作りたいのであれば必須といえます。
ですが、そのためにはSQLやデータベース管理ソフトウェア(DBMSといいます)の使い方の知識も必要になってきます。今回は最低限のPHPとHTMLの知識で掲示板を作ることを重視します。
PHPと一緒にこれらの知識を学習した方は、ぜひ応用として自力でデータベース利用版を考えてみてください。
以上、前提になる設定が整いましたので、次の章から実際に掲示板を組み立てていきましょう。
ファイルに書き込みを記録する
まずはフォームに記入された内容をPHPに投げる方法を確認していきましょう。これはHTMLのform、PHPのPOST,GETの両方の分野にまたがる内容になるので、苦手意識の有る方も多いかもしれません。
以下の記事でそれぞれ詳しく解説していますので、あまり得意でない方はぜひご確認ください。
今回はすでにHTMLを書いているので、こちらをベースに説明を進めていきます。確認のため、PHPとやり取りをする部分だけ抜き出すと次のようになります。
<form action="bord.php" method="post"> <div> <label for="name">名前</label> <input type="text" id="name" name="name"> </div> <div> <label for="message">内容</label> <input type="text" id="message" name="message"> </div> <input type="submit" name="send" value="送信する"> </form>
確認すると、POST情報として、nameとmessageが投げられていることがわかりますね。では、これらの情報をPHP側で処理していきましょう。PHPの処理をHTMLの上に追加していきます。
まずは、POSTで投げられた情報を変数に格納しましょう。POSTの情報は $_POSTという変数に格納されています。以下のように $_POST変数にinputタグのname属性を記入してあげることで、POSTされた情報を引き出すことができます。
<?php $name = $_POST["name"]; $message = $_POST["message"]; ?>
そして、今回は送信するボタンが押された時にデータの書き込み処理をしたいので、ボタンが押されたことを判定する処理を作り込んでいきます。
といってもやることは意外と単純です。POST情報の内、sendがtrueになっていればボタンが押されたと判断できるので、if文を使って次のように記述してあげればボタンが押されたことを判定できます。
<?php if(isset($_POST['send']) === true){ #ボタンが押された時に実行したい処理 } ?>
なので、これらの処理をまとめると、以下のように書くことで、目的が達成できそうです。
<?php $name = ""; $message = ""; if(isset($_POST['send']) === true){ $name = $_POST["name"]; $message = $_POST["message"]; #テキストファイルに$name,$messageを書き込む処理 } ?>
では次に、ファイルに情報を書き込む処理について見ていきましょう。
PHPのファイル書き込み処理
PHPでファイルに書き込む方法を確認して行きましょう。PHPでファイルに読み書きを行うにはfopen関数を使うのが一般的です。
fopen関数の詳しい使い方は以下の記事で紹介していますので、各自確認いただくとして、今回やりたいことはファイルに掲示板で投稿された名前と内容を記録することです。
このとき必要なのはファイルの追記処理です。書き込み専用でファイルをオープンして、ファイル末尾に書き込む情報を追加し、ファイルをクローズすれば良さそうですね。
データを書き込むテキストファイルをbord.txtとして、bord.phpと同じ階層に置いて処理していくとします。このとき、今まで書いてきた処理を実現するには以下のようなコードになります。
<?php $name = $_POST["name"]; $message = $_POST["message"]; $fp = fopen("bord.txt", "a"); fwrite($fp,$name . "t" . $message . "n"); fclose($fp); ?>
PHPのfopen関数を追記モードで使う場合、上のようにファイル名の後ろのモード設定で文字列のaを指定します。
fopen関数でファイルポインタ$fpを取得して、追記モードで掲示板に投稿された名前と情報を$name . “t” . $message . “n”という形式でファイルに書き込みます。
これは 名前 タブ 内容 改行 という形式ですね。
最後にファイルをクローズして、一連のファイル操作が完了です。実はfclose関数は無くてもプログラム自体は動くのですが、プログラミングの基本としてファイルはオープンしたらクローズする、という物があるので、初心者のうちはお約束に従っておきましょう。
これで、HTMLからPOST情報を受け取って、その情報をテキストファイルに記録する手段が整いました。これらを組み合わせることで設計の1.2.で示した記録部分を実現することができます。
<?php $name = ""; $message = ""; if(isset($_POST['send']) === true){ $name = $_POST["name"]; $message = $_POST["message"]; $fp = fopen("bord.txt", "a"); fwrite($fp,$name . "t" . $message . "n"); fclose($fp); } ?>
これをHTMLの上に追加して、ファイル名をbord.phpとし、ローカルサーバに置いてアクセスすることで書き込みの記録のみできる掲示板が完成しました。
成果を確認したい方はぜひ動かしてみましょう。1番最初のみテキストファイルの生成ができておらずエラーが出ますが、それ以降は書いた内容がbord.txtにどんどん記録されていく様子が確認できますよ。
テキストファイルの情報を表示する
この章ではテキストファイルに書き込まれている情報を表示する方法を見ていきます。
現在、投稿データを保持しているテキストファイル、bord.txtの内容は以下のようになっているはずです。
山田(タブ文字)書き込み内容(改行) たかし(タブ文字)書き込み内容(改行) 山田(タブ文字)書き込み内容(改行) ……
なので、この情報を取り出して、HTMLに反映させてあげれば、設計の「3.記録されている内容を表示欄にすべて表示する」を実現できますね。
なので、まずはテキストファイルから情報を取り出す方法を確認しましょう。PHPでテキストファイルからデータを読み込むにはfget関数を使います。
fget関数について詳しくは上で紹介したfopen関数の使い方にまとめてありますので、不安な方は一度ご確認ください。
ファイル操作なので、先程と同様にまずはファイルポインタを取得します。今回は情報の読み込みなので、”r”オプションを使いますので、気をつけてください。
$fp = fopen("bord.txt", "r");
続いてfget関数を使って、ファイルを読み込みます。ここで注意点ですが、fget関数はテキストファイルを1行単位で読み込みます。そのため、操作も1行ずつとなりますので、実際に利用する際は記録の時点から使いやすいように気をつかいましょう。
$line = fgets($fp);
そして、取り出してきた行を使いやすいように加工します。今回は名前と書き込み内容を分割したほうが使いやすいので、explode関数を使って文字列を分割していきましょう。
explode関数は指定した区切り文字をつかって文字列を分割することができる関数です。分割された文字列は配列として返される点も覚えておきましょう。
今回は、名前と書き込み内容をタブ文字で区切ってあるので、以下のようにすることでtemp変数に名前と書き込み内容を分割して格納できます。
$temp = explode("t", $line);
そして、格納された文字列を使いやすいように連想配列に入れ直します。キーはこれまでと同じようにname,messageで統一しておきましょう。
$temp_array = [ "name" => $temp[0], "message" => $temp[1] ];
あとは、今までやってきた処理をwhileでbord.txtに記載されている行数分行えば、すべての書き込み情報を配列に格納することができますね。
while文を使って情報を$bord_array[]に格納する方法が以下になります。
<?php $fp = fopen("bord.txt", "r"); $bord_array = []; while ($line = fgets($fp)) { $temp = explode("t", $line); $temp_array = [ "name" => $temp[0], "message" => $temp[1] ]; $bord_array[] = $temp_array; } ?>
では、今度は$bord_array[]の中身をHTMLに反映させていきましょう。
配列の中身を取り出しながらループを回すなら、foreach文ですね。なので、まずは以下のような構造を考えてみましょう。
<?php foreach($bord_array as $data){ echo $data["name"].":".$data["message"]; } ?>
これを回すと、確かに書き込み内容をすべて出力することはできます。ただし、改行が入らず一直線に並んでしまいますが……
山田(タブ文字)書き込み内容たかし(タブ文字)書き込み内容山田(タブ文字)書き込み内容(改行)……
これを回避するための考え方はいろいろあります。たとえば、$data[“message”]の後ろにnを結合して強制的に改行する、というのもありでしょう。
ただ、今回は見た目のいじりやすさから、箇条書きを利用します。特に手を加えなくてもそれっぽく見えるというのも採用理由ですが。
ともかく、箇条書きを使う場合、このforeach文を箇条書きのulタグで囲み、各書き込みをそれぞれliタグで囲う必要があります。liタグを文字列として結合しても問題なく動作しますが、見た目をスッキリさせるためにコロン構文とショートコードを使ってみましょう。
コロン構文は名前のとおり、PHPで利用できるコロン(:)を使った書き換え方法です。HTMLとPHPのコードが混ざっている場所で活用すると、視認性が向上します。
<?php foreach():?> <?php …… ?> <?php endforeach;?> #以下と同じ意味 <?php foreach(){ …… } ?>
単体で見ると ?PHP の数が増加していて視認性が向上しているようには見えませんが、HTMLとPHPが複雑に混ざってくると、foreachの場所が明確にわかるため視認性が向上するわけです。
コロン構文とセットでよく用いられるのが <?= のショートコードです。PHP5.4.0以降でないと使えないため、環境が少々限定されますが、これは以下のように文字表示で頻出のechoを簡単に書くための省略記法です。
<?= ……?> #以下と同じ意味 <?php echo …… ?>
慣れないうちは違和感があると思いますが、使い慣れると簡単に文字表示ができて非常に便利で見た目もスッキリするので、ぜひ活用してください。
以上の知識を合わせて、文字表示を整形していきます。まずはコロン構文に書き換えます。
<?php foreach($bord_array as $data):?> <?php echo $data["name"].":".$data["message"];?> <?php endforeach; ?>
続いてul,liタグを追加します。
<ul> <?php foreach ($bord_array as $data):?> <?php echo "<li>"?> <?php echo $data["name"].":".$data["message"];?> <?php echo "</li>"?> <?php endforeach;?> </ul>
最後に<?= に置き換えます。
<ul> <?php foreach ($bord_array as $data):?> <?= "<li>"?> <?= $data["name"].":".$data["message"];?> <?= "</li>"?> <?php endforeach;?> </ul>
かなり見やすく、かつ処理内容が理解できる書き方に落ち着いたのではないでしょうか?
以上で1行掲示板の全部の情報が出揃いました。すべてをまとめると以下のようになります。
<?php $name = ""; $message = ""; if (isset($_POST['send']) === true) { $name = $_POST["name"]; $message = $_POST["message"]; $fp = fopen("bord.txt", "a"); fwrite($fp, $name . "t" . $message . "n"); fclose($fp); } $fp = fopen("bord.txt", "r"); $bord_array = []; while ($line = fgets($fp)) { $temp = explode("t", $line); $temp_array = [ "name" => $temp[0], "message" => $temp[1] ]; $bord_array[] = $temp_array; } ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>testbord</title> </head> <body> <form action="" method="post"> <div> <label for="name">名前</label> <input type="text" id="name" name="name"> </div> <div> <label for="message">内容</label> <input type="text" id="message" name="message"> </div> <input type="submit" name="send" value="送信する"> </form> <h2>表示欄</h2> <ul> <?php foreach ($bord_array as $data): ?> <?= "<li>" ?> <?= $data["name"] . ":" . $data["message"]; ?> <?= "</li>" ?> <?php endforeach; ?> </ul> </body> </html>
お疲れ様でした!
PHPのセキュリティ対策について
最後にセキュリティ対策について、少しだけ触れておきます。
上の方でも説明しましたが、このコードは全体の視認性や理解のしやすさを優先しているため、セキュリティ対策を一切施していません。そのため、不特定多数の利用が想定される場所で公開すると、あっという間にXSSなどの餌食になります。
自分だけでなく、周囲の方にも迷惑をかけることになってしまうので、オープンな環境への公開は絶対に止めてくださいね。
セキュリティに関心の有る方は、以下の本を参考にされると良いでしょう。
PHPを効率的に学べるサービス
何から学び始めればいいの?
難しそうだし、挫折したらやだな…。
ここまで掲示板の作り方やPHPのファイル書き込み処理などについて解説してきましたが、上記のような悩みを持っている方も多いですよね。
そんな方には、サブスク型のプログラミングスクール「SAMURAI TERAKOYA」がおすすめです。
登録無料で、主に4つのサービスを提供させていただきます。
- 現役エンジニアによる月1度の「マンツーマン指導」
- 平均回答時間30分の「Q&Aサービス」
- 作りながら学べる28種類の「教材」
- 学習を記録&仲間と共有できる「学習ログ」
目的にあった教材を選べば、どなたでも効率よく学習できるほか、Q&Aサービスやマンツーマン指導を活用することで、挫折せずにPHPの習得が可能です。
PHPを効率的に学びたい人はもちろん、何から始めたらよいのかわからない方は、ぜひ「SAMURAI TERAKOYA」をご利用ください。
詳細はこちらまとめ
いかがでしたか?
今回はPHPを使って簡単な1行掲示板の実装をステップ・バイ・ステップで行ってきました。
見た目はしょぼい一品ですが、実際に実装しようとすると意外なほど手間がかかることが実感できたのではないでしょうか?
この後は、EC-Cube辺りのソースコードを読んでみるのもオススメです。余力の有る方は是非どうぞ。
この記事を踏み台に、PHPの応用的なプログラミングに踏み出すお手伝いができたなら、筆者としてはとても嬉しいです。