「ドラ○も~~~ん!!!掲示板が欲しい!あんま複雑な機能いらないから掲示板が欲しい!!」
ログ読み込み ⇒ 書き込み ⇒ ログ記録 の基本的な機能なんで
PHPとJavaScriptで簡易的な掲示板作ってみます!!
完成デモページとシステム上の注意点
完成したページが
コチラ
システムの仕様上、ログファイルの排他処理を行っていません。
投稿されたデータはその後に別の人がアクセスした際に出力されてしまうので、
お前らぁ・・・ぜぇったいにぃ~~~
ぜぇ~~~ったいにぃ~~~荒らすなよぉ~~~!!!!(※フリでは無いです)
※この他、複数ユーザーが同時に書き込みを行ったときに、タイミングが重なり、正しく投稿が記録されなかったり、あるいはログファイルが壊れてしまったりする可能性や、
表示数の制限もないため大量に記録されたデータをすべて表示するとログファイルの読み込みに時間がかかってしまいます。
必要なファイルと概要
①投稿データログ用ファイル『log.json』
投稿されたデータを記録するためのjson形式のファイルです。
ファイルの内容はシステムが動作した際に記録されるため、空のファイルを準備すればOKです。
例えば名前に「
YANYO」、本文に「
TEST」と投稿した場合、『log.json』に以下の様に記録されます。
{"date":2015\/09\/18 00:00:00","name":"YANYO","TEST"}
②掲示板のHTMLファイル『bbs.html』
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>PHPとJavaScriptで簡易掲示板作ってやんよ!!!デモページ</title>
<script type="text/javascript" src="bbs.js"></script>
<style>
h1, h2 { background-color:#F90; padding: 6px; color: #fff;}
input { width: 300px; }
</style>
</head>
<body>
<h1>PHPとJavaScriptで簡易掲示板作ってやんよ!!!デモページ</h1>
<div>名前:<input id="name" type="text" /><br>
本文:<input id="body" type="text" />
<button id="postBtn">投稿</button>
</div>
<h2>ログ</h2>
<div>
<ul id="logList"></ul>
</div>
</body>
</html>
記録されたログデータは「
<ul id="logLisl">」内にひと項目につき
<li>としてサーバーから読み込んだデータを流し込みます。
③JavaScriptファイル「bbs.js」
// 初期化処理
window.onload = function() {
// ボタンが押されたイベントハンドラを設定
$("postBtn").onclick = writeLog;
// ログを読み込む
showLog();
};
// ログの表示
function showLog() {
// Ajaxでログを取得
ajaxGet(
"api.php?type=getLog",
function (xhr, text) {
var logs = JSON.parse(text);
renderLog(logs);
});
};
// ログデータに基づき描画
function renderLog(logs) {
var html = "";
for(var i in logs) {
var m = logs[i];
var date = m["date"];
var name = m["name"];
var body = m["body"];
html += "<li>" + date + ":" + name + "<br>「" + body + "」</li>";
}
$("logList").innerHTML = html;
}
// 書き込みを投稿する
function writeLog() {
var name = $("name").value;
var body = $("body").value;
var params = "type=writeLog&" + "nam=" + encodeURI(name) + "&" + "body=" + encodeURI(body);
ajaxGet("api.php?" + params, function(xhr, text) {
// テキストフィールドを初期化
$("body").value = "";
// 書き込みを反映
showLog();
});
}
// Ajax用
function ajaxGet(url, callback) {
// XMLHttpRequestのオブジェクトを作成
var xhr = new XMLHttpRequest();
// 非同期通信でURLをセット
xhr.open('GET', url, true);
// 通信状態が変化したときのイベント
xhr.onreadystatechange = function() {
if(xhr.readyState == 4) {
if(xhr.status == 200) {
callback(xhr, xhr.responseText);
}
}
};
xhr.send('');
return xhr;
}
// 任意のIDを得る
function $(id) {
return document.getElementById(id);
}
ログの表示
showLog関数では、Webサーバーにある「api.php」に接続し、「api.php」のgetLog関数を実行することで、Webサーバーからログを取得します。
ログの取得が完了すると、無名関数として記述しているコールパック関数が呼ばれます。
ログのデータはJSON形式で送られてくるので、このコールパック関数の中でJSON.parse関数を使ってJSONのデータをJavaScriptのオブジェクトに変換し、renderLog関数に渡します。
ログデータに基づき描画
renderLog関数では、渡されたオブジェクトからnameとbodyのデータを取り出して、HTMLのli要素を使って格形し、logListに表示します。
書き込みを投稿する
input要素の値を取り出し、書き込み用のパラメータparamsを作成して、それを付加して「api.php」を呼び出します。
Webサーバーへの書き込みが完了すると、コールパック関数が呼ばれます。
「body」テキストフィールドを消し、改めてshowLogl関数を呼び出して最新のログを表示します。
Ajaxで非同期通信
XMLHttpRequestオブジェクト(非同期なデータの通信を実現するためのAPI)を利用して非同期通信を行います。
「api.php」とGETの値を引数に、onreadystatechangeはreadyState属性が変更されるたびに呼び出されたイベントハンドラを返します(4:リクエストは終了してレスポンスの準備が完)とサーバがリクエストに対してどのように応答したか(200:OK)の条件をクリアする事でコールバック関数で通信を行ったデータをwriteLogに戻し書き込みを反映します。
④PHPプログラム『api.php』
// 定数の定義
define("LOGFILE", "log.json");
// ログファイルの確認
if(!file_exists(LOGFILE)) {
file_put_contents(LOGFILE, "[]");
}
// typeの値に応じて分岐
$type = isset($_GET["type"]) ? $_GET["type"] : "";
if($type == "getLog") {
getLog();
} elseif($type == "writeLog") {
writeLog();
}else {
echo "[]";
exit;
}
// ログの取得処理
function getLog() {
$json = file_get_contents(LOGFILE);
if($json == "") $json = "[]";
echo $json;
}
// ログの書き込み
function writeLog() {
// パラメーターを得る
$name = !empty($_GET["name"]) ? $_GET["name"] : "名無し";
$body = isset($_GET["body"]) ? $_GET["body"] : "";
if($body == "") {
echo '{"stat" : "error", "msg" : "本文がありません"}';
exit;
}
// ログに追記
$name = htmlspecialchars($name);
$body = htmlspecialchars($body);
date_default_timezone_set('Asia/Tokyo');
$date = date("Y/m/d H:i:s");
$json = file_get_contents(LOGFILE);
$a = json_decode($json);
if(!is_array($a)) { $a = array(); }
array_unshift($a, array("date" => $date, "name" => $name, "body" => $body));
$json = json_encode($a);
file_put_contents(LOGFILE, $json);
echo '{"stat":"ok"}';
}
このファイルの役割は「log.json」に対する読み書きです。
通信ファイルへのパラメーターの役割
「bbs.js」から「api.php」にアクセスする時は
「api.php?」以下に"typeパラメータ”を付けています。
showLog関数の中では「type=getLog」、writcLog関数で「type=writeLog」というパラメータを付けています。
showLog関数からアクセスされた場合はgetLog関数を実行し、writeLog関数からアクセスされた場合はwriteLog関数を実行します。
isset関数と3項演算子でパラメーターチェック
$_GET["type"]を参照すると、存在しない変数にアクセスしたとして、PHPの「NOTICEエラー」を回避するために、
変数が存在するかどうかをチェックする「isset関数」を使います。
$type = isset($_GET["type"]) ? $_GET["type"] : "";
htmlspecialchars関数で「<」や「>」を変換
掲示板のユーザーが書き込んだ名前や本文の中にHTMLタグの開始を示す「く」や終了を示す「>」などがあると、レイアウトが崩れたり、セキュリティ上の問題になる可能性があります。
そこで、PHPのhtmlspecialchars関数を利用して、
HTMLの特殊文字である「<」「>」「&」を「&lt;」「&gt;」「&amp;」という"HTMLエンテイテイ"に変換しておきます。