pagetop

BLOG

【Mysql入門】phpでシンプルチャット作ってみた

  • HOME

  • BLOG

  • 【Mysql入門】phpでシンプルチャット作ってみた

Article

【Mysql入門】phpでシンプルチャット作ってみた

PHP

Mysqlを構築しphpで呼び出すプログラムの入門編として、シンプルなチャットを構築してみました。

 

今回の要件

一応チャットということで、以下のように要件定義してみました。

  • 名前とメッセージを投稿できる
  • 投稿が新しい順に上から表示する
  • 削除できる
  • メッセージ検索できる

すごくシンプルな要件です。入門編にはちょうどいいかなと…

 

Mysqlを構築する

まずは、Mysqlを構築します。
今回はサーバーのコンパネからDBを追加し、phpmyadminでテーブルを作成します。

DB名は「chatdb」とし作成するテーブルは「chattbl」とします。

phpmyadminのコンパネから「chattbl」を作成し、以下のような内容でテーブルの中身を構築します。

phpmyadmin

名前のデータの内容は以下です。

  • 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に変数設定するだけです。

ここまでで以下のように表示されます。

chat

 

投稿を検索する

投稿されたメッセージ本文を検索します。

 

検索フォームを作成する

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の入門編としては、ちょうどいいテーマではないでしょうか?

これをベースに(なるかどうかは不明ですが..)会員登録とユニーク投稿を実装など発展させたいと思います。

Spread the love