
Mysqlを構築しphpで呼び出すプログラムの入門編として、シンプルなチャットを構築してみました。
今回の要件
一応チャットということで、以下のように要件定義してみました。
- 名前とメッセージを投稿できる
- 投稿が新しい順に上から表示する
- 削除できる
- メッセージ検索できる
すごくシンプルな要件です。入門編にはちょうどいいかなと…
Mysqlを構築する
まずは、Mysqlを構築します。
今回はサーバーのコンパネからDBを追加し、phpmyadminでテーブルを作成します。
DB名は「chatdb」とし作成するテーブルは「chattbl」とします。
phpmyadminのコンパネから「chattbl」を作成し、以下のような内容でテーブルの中身を構築します。

名前のデータの内容は以下です。
- number 投稿順にカウントされる数字
- name 投稿名
- mes メッセージ
- ymddate 投稿日時
numberに入る数字が大きいものから上から順に表示されます。
フォームを作成する
投稿用のフォームを作成します。
index.php
<form action="index.php" method="post" name="form"> 名前<input type="text" name="n"> メッセージ<textarea name="m"></textarea> <input type="submit" value="送信" name="submit"> </form>
DBに投稿されたデータを書き込む
フォームから投稿された内容をDBに書き込みます。
index.php
<?php
if(isset($_POST['n'])) {
$dsn= "mysql:host=localhost;dbname=chatdb;charset=utf8";
$user="DBのユーザー名";
$pass="DBのパスワード";
$my_nam=htmlspecialchars($_POST["n"], ENT_QUOTES);
$my_mes=htmlspecialchars($_POST["m"], ENT_QUOTES);
try{
$db = new PDO($dsn,$user,$pass);
$db->query("INSERT INTO `chattbl` (number,name,mes,ymddate)
VALUES (NULL,'$my_nam','$my_mes',NOW())");/
}catch (Exception $e) {
echo $e->getMessage() . PHP_EOL;
}
header("Location: {$_SERVER['PHP_SELF']}");
exit;
}
?>
フォームアクション後、DBに書き込むようにしています。WPを利用されている方なら見慣れてると思いますが、構築したDBへのアクセス設定をします。
$dsn= "mysql:host=localhost;dbname=chatdb;charset=utf8"; $user="DBのユーザー名"; $pass="DBのパスワード";
名前を$my_namに、メッセージを$my_mesに代入し、SQL文で’chat-tb’テーブルに番号・名前・メッセージ・日付の内容を取得して保存してます。
VALUES (NULL,'$my_nam','$my_mes',NOW())");
エラーが出たときの処理は以下です。
echo $e->getMessage() . PHP_EOL;
処理後もとのページに戻ります。
header("Location: {$_SERVER['PHP_SELF']}");
exit;
DBから情報を呼び出し投稿内容表示する
投稿内容を表示します。
index.php
<?php
$dsn= "mysql:host=localhost;dbname=chatdb;charset=utf8";
$user="DBのユーザー名";
$pass="DBのパスワード";
$db = new PDO($dsn,$user,$pass);
$ps = $db->query("SELECT * FROM `chattbl` ORDER BY number DESC");
define("SECMINUITE", 60); //1分(秒)
define("SECHOUR", 60 * 60); //1時間(秒)
define("SECDAY", 60 * 60 * 24); //1日(秒)
define("SECWEEK", 60 * 60 * 24 * 7); //1週(秒)
define("SECMONTH", 60 * 60 * 24 * 30); //1月(秒)
define("SECYEAR", 60 * 60 * 24 * 365); //1年(秒)
function niceTime($dest,$sour) {
$sour = (func_num_args() == 1) ? time() : func_get_arg(1);
$tt = $dest - $sour;
if ($tt / SECYEAR < -1) return abs(round($tt / SECYEAR)) . '年前';
if ($tt / SECMONTH < -1) return abs(round($tt / SECMONTH)) . 'ヶ月前';
if ($tt / SECWEEK < -1) return abs(round($tt / SECWEEK)) . '週間前';
if ($tt / SECDAY < -1) return abs(round($tt / SECDAY)) . '日前';
if ($tt / SECHOUR < -1) return abs(round($tt / SECHOUR)) . '時間前';
if ($tt / SECMINUITE < -1) return abs(round($tt / SECMINUITE)) . '分前';
if ($tt < 0) return abs(round($tt)) . '秒前';
if ($tt / SECYEAR > +1) return abs(round($tt / SECYEAR)) . '年後';
if ($tt / SECMONTH > +1) return abs(round($tt / SECMONTH)) . 'ヶ月後';
if ($tt / SECWEEK > +1) return abs(round($tt / SECWEEK)) . '週間後';
if ($tt / SECDAY > +1) return abs(round($tt / SECDAY)) . '日後';
if ($tt / SECHOUR > +1) return abs(round($tt / SECHOUR)) . '時間後';
if ($tt / SECMINUITE > +1) return abs(round($tt / SECMINUITE)) . '分後';
if ($tt > 0) return abs(round($tt)) . '秒後';
return '現在';
}
try{
while($r = $ps->fetch()){
$beforedest = $r['ymddate'];
$dest = strtotime($beforedest);
$sour = time(); //現在の時刻を$sourに代入
$outstr = nicetime($dest,$sour);
$pattern = '/((?:https?|ftp):\/\/[-_.!~*\'()a-zA-Z0-9;\/?:@&=+$,%#]+)/';
$replace = '<a href="$1" target="_blank">$1</a>';
$r['mes']=preg_replace( $pattern, $replace, $r['mes'] );
?>
<div>
<?php
print "{$r['number']}";
?>
<br>
<?php
print "{$r['name']}";
?>
<?php
echo $outstr;
?>
<?php
print nl2br($r['mes']);
?>
<a href="delete.php?number=<?php print "{$r['number']}";?>">削除</a>
</div>
<hr>
<?php }
}catch(Exception $e){
echo $e->getMessage() . PHP_EOL;//エラーが出たときの処理
}
?>
DBにアクセスし、テーブルから番号の降順に投稿内容を取得します。
$dsn= "mysql:host=localhost;dbname=chatdb;charset=utf8";
$user="DBのユーザー名";
$pass="DBのパスワード";
$db = new PDO($dsn,$user,$pass);
$ps = $db->query("SELECT * FROM `chattbl` ORDER BY number DESC");
何分前の投稿か取得します。
define("SECMINUITE", 60); //1分(秒)
define("SECHOUR", 60 * 60); //1時間(秒)
define("SECDAY", 60 * 60 * 24); //1日(秒)
define("SECWEEK", 60 * 60 * 24 * 7); //1週(秒)
define("SECMONTH", 60 * 60 * 24 * 30); //1月(秒)
define("SECYEAR", 60 * 60 * 24 * 365); //1年(秒)
function niceTime($dest,$sour) {
$sour = (func_num_args() == 1) ? time() : func_get_arg(1);
$tt = $dest - $sour;
if ($tt / SECYEAR < -1) return abs(round($tt / SECYEAR)) . '年前';
if ($tt / SECMONTH < -1) return abs(round($tt / SECMONTH)) . 'ヶ月前';
if ($tt / SECWEEK < -1) return abs(round($tt / SECWEEK)) . '週間前';
if ($tt / SECDAY < -1) return abs(round($tt / SECDAY)) . '日前';
if ($tt / SECHOUR < -1) return abs(round($tt / SECHOUR)) . '時間前';
if ($tt / SECMINUITE < -1) return abs(round($tt / SECMINUITE)) . '分前';
if ($tt < 0) return abs(round($tt)) . '秒前';
if ($tt / SECYEAR > +1) return abs(round($tt / SECYEAR)) . '年後';
if ($tt / SECMONTH > +1) return abs(round($tt / SECMONTH)) . 'ヶ月後';
if ($tt / SECWEEK > +1) return abs(round($tt / SECWEEK)) . '週間後';
if ($tt / SECDAY > +1) return abs(round($tt / SECDAY)) . '日後';
if ($tt / SECHOUR > +1) return abs(round($tt / SECHOUR)) . '時間後';
if ($tt / SECMINUITE > +1) return abs(round($tt / SECMINUITE)) . '分後';
if ($tt > 0) return abs(round($tt)) . '秒後';
return '現在';
}
それぞれの投稿内容(名前+メッセージ+番号+日時)を$rに代入しタイムスタンプに変換して、while文とfetch関数を使用して表示します。
while($r = $ps->fetch()){
$beforedest = $r['ymddate'];
$dest = strtotime($beforedest);
$sour = time(); //現在の時刻を$sourに代入
$outstr = nicetime($dest,$sour);
また、メッセージの内容にURLが入っていた場合、自動的にリンク設定します。
$pattern = '/((?:https?|ftp):\/\/[-_.!~*\'()a-zA-Z0-9;\/?:@&=+$,%#]+)/'; $replace = '<a href="$1" target="_blank">$1</a>'; $r['mes']=preg_replace( $pattern, $replace, $r['mes'] );
あとはhtmlに変数設定するだけです。
ここまでで以下のように表示されます。

投稿を検索する
投稿されたメッセージ本文を検索します。
検索フォームを作成する
search.php
<form action="result.php" method="post"> 検索キーワード<input type="text" name="s"> <input type="submit" value="検索"> </form>
検索ページを構築する
検索結果を表示します。今回はヒットしない場合は単純にブランクなのでご勘弁を。
result.php
$my_sea=htmlspecialchars($_POST["s"], ENT_QUOTES);
$dsn= "mysql:host=localhost;dbname=chatdb;charset=utf8";
$user="DBのユーザー名";
$pass="DBのパスワード";
$db = new PDO($dsn,$user,$pass);
print "<p>「{$my_sea}」の検索結果</p>";
$ps=$db->query("SELECt * FROM `chattbl` WHERE mes like '%$my_sea%'");
while($r = $ps->fetch()){
$pattern = '/((?:https?|ftp):\/\/[-_.!~*\'()a-zA-Z0-9;\/?:@&=+$,%#]+)/';
$replace = '<a href="$1" target="_blank">$1</a>';
$r['mes']=preg_replace( $pattern, $replace, $r['mes'] );
print "{$r['name']} {$r['ymddate']}<br>".nl2br($r['mes'])."<hr>";
}
print "<p><a href='index.php'>一覧表示へ</a></p>";
パターンマッチングを行い、検索結果を表示します。
$ps=$db->query("SELECt * FROM `chattbl` WHERE mes like '%$my_sea%'");
while($r = $ps->fetch()){
print "{$r['name']} {$r['ymddate']}<br>".nl2br($r['mes'])."<hr>";
}
投稿を削除する
何かと発言が炎上する世の中です。まずい!と思ったら削除しましょう。
delete.php
<?php
try {
$user="DBのユーザー名";
$pass="DBのパスワード";
$dbh = new PDO("mysql:host=localhost;dbname=chatdb;charset=utf8", "$user", "$pass");
$stmt = $dbh->prepare('DELETE FROM chattbl WHERE number = :number');
$stmt->execute(array(':number' => $_GET["number"]));
header('Location: index.php');
exit;
} catch (Exception $e) {
echo 'エラーが発生しました。:' . $e->getMessage();
}
?>
<p><a href='index.php'>一覧表示へ</a></p>
<a href="delete.php?number=<?php print "{$r['number']}";?>">削除</a>
上記のリンクにnumberをクエリとして入れています。それをGETし削除し、投稿ページにリダイレクトします。
$stmt = $dbh->prepare('DELETE FROM chattbl WHERE number = :number');
$stmt->execute(array(':number' => $_GET["number"]));
header('Location: index.php');
以上です。
Mysqlの入門編としては、ちょうどいいテーマではないでしょうか?
これをベースに(なるかどうかは不明ですが..)会員登録とユニーク投稿を実装など発展させたいと思います。