MySQL(ver.5.0)

第5章 BBS

前へ | 目次へ |次へ  | YCポータルサイト

5.2 編集・引用可能なBBS(タイプ2)

データベースの作成
URLの登録
削除可能なBBS
更新可能なBBS
引用可能なBBS
メールで送信可能なBBS

5.2 再編集・引用可能なBBS(タイプ2)

 再編集(削除、更新)・引用可能な電子掲示板(BBS(タイプ2))を作成することにより、以下のWebアプリケーションの基礎技術を習得します。

・URLの登録
・記事の削除
・記事の更新

■データベースの作成

 以下に制作するBBSの記事は、タイプ1のBBSに対して「更新日」、「URL」、「パスワード」、「親記事番号」を含むものとします。これをタイプ2BBS(BBS2)と呼ぶこととします。

フィールド名 長さ 説明 備考
message_id INTEGER   記事番号 主キー:自動入力
name CHAR 64 投稿者氏名 ブラウザから入力
title VARCHAR 255 タイトル ブラウザから入力
message TEXT   記事本文 ブラウザから入力
date DATETIME   投稿日時 自動入力
date_update DATETIME 更新日 自動入力
url VARCHAR 255 URL ブラウザから入力
pwd CHAR 32 パスワード ブラウザから入力
parent_id INTEGER 親記事番号 自動入力
mail VARCHAR 255 メールアドレス ブラウザから入力

 データベース「db_bbs」の中に、上記のテーブル名を「tbl_bbs2」として作成します。

■URLの登録

 記事を投稿する場合、記事に関連するURLも投稿したくなる場合があります。

 ただ、記事の中にURLを記述できるようにするためには、記事にHTMLタグの記入を許容する必要があります。ただ、「5.1セキュリティ対策等のための文字列変換」の項で述べたように、記事の中にHTMLタグの記入を許容することはセキュリティ対策上好ましくありません。

 そこで、URLのみを記述できる入力欄を新たに設けることとします。

(1)記事入力フォームへのURL入力欄の追加

 まず、5.1で作成したインクルードファイルcommon_bbs1.phpの中の入力フォーム表示用のユーザ定義関数「input_form_disp()」を以下のように改造します。URL入力欄には初期値として「http://」と表示するようにします。

// ----------------------------------------------
// 入力フォームの表示
function input_form_disp(&$str_name,&$str_title,&$str_message,&$str_url)
{
/*
$str_name  :投稿者氏名
$str_title  :記事タイトル
$str_message :記事本文
$str_url  :関連URL
*/
 // 改行タグの改行コードへの変換
 $str_message = tag_entity_form($str_message);
 
 // URL欄の初期値設定
 if($str_url == "")
 {
  $str_url = "http://";
 }
?>
<table border="0">
<form method="post" action='<?=THIS_FILE?>'>
<tr>
 <td> </td><td>BBS1</td>
</tr>
<tr>
 <td>氏名</td><td><input name="name" size="30"
             value="<?=$str_name?>"></td>
</tr>
<tr>
 <td>タイトル</td><td><input name="title" size="60"
               value="<?=$str_title?>"></td>
</tr>
<tr>
 <td>記事</td>
 <td><textarea name="message"
        rows="5" cols="60"><?=$str_message?></textarea></td>
</tr>
<tr>
 <td>URL</td><td><input name="url" size="60"
            value="<?=$str_url?>"></td>
</tr>

<tr>
 <td> </td><td><input type=submit name="command" value="送信"></td>
</tr>
</form>
</table>
<?php
}

(2)受信URLのチェック

 受信したURLデータが、URLとして正しい文字列かどうか、セキュリティ対策上チェックする必要があります。

 URL文字列$str_urlは、Perl互換の正規表現として、たとえば以下の正規表現に一致する必要があります。

preg_match('/^http(s?)\:\/\/[\w\.\-\/\?\&\+\=\:\@\%\#]+$/',$str_url)

 ただ、受信URLの文字列が「http://」の場合は、初期値のままで未入力状態なので、この場合は受信URL文字列は「http://」でなく空にします。

 サンプルスクリプトでは、一致すべき正規表現パターンを定数MATCH_URLとして、インクルードファイルsystem02a.php内に定義して使用することとします。

system02a.php

<?php
define(MATCH_URL,"/^http(s?)\:\/\/[\w\.\-\/\?\&\+\=\:\@\%\#]+$/");
?>

 この定数MATCH_URLを使用して、5.1で作成したインクルードファイルcommon_bbs1.phpの中の受信データチェック用のユーザ定義関数「data_check()」を以下のように改造します。

// ----------------------------------------------
// 受信データのチェック
function data_check(&$str_name,&$str_title,&$str_message,&$str_url)
{
/*
$str_name :投稿者氏名
$str_title :記事タイトル
$str_message :記事本文
$str_url :関連URL
*/
 global $str_charset;
 disp_var(1,$str_charset,'$str_charset');
 // データの受信
 $str_name = $_POST['name'];
 $str_title = $_POST['title'];
 $str_message = $_POST['message'];
 $str_url = $_POST['url'];

 $str_name = tag_entity_input($str_name,$str_charset);
 $str_title = tag_entity_input($str_title,$str_charset);
 $str_message = tag_entity_input($str_message,$str_charset);

 // 文字列の前後の半角スペースを削除し、半角カタカナを全角カタカナに変換
 $str_name = input_str_convert($str_name);
 $str_title = input_str_convert($str_title);
 $str_message = input_str_convert($str_message);
 // 文字列が空かいなかのチェック
 if($str_name == "")
 {
  $str = "氏名を記入してください";
 }
 elseif($str_title == "")
 {
  $str = "タイトルを記入してください";
 }
 elseif($str_message == "")
 {
  $str = "本文を記入してください";
 }
 elseif($str_url != "http://")
 {
  if(!preg_match(MATCH_URL,$str_url))
  {
   $str = "URLを正しく記入してください";
  }
 }
 elseif($str_url == "http://")
 {
  $str_url = "";
 }

 return $str;
}

(3)URLデータのデータベースへの保存

 5.1で作成したメインファイルmain01l.phpファイルを以下のように改造し、main02a.phpファイルとします。また、5.1で作成した検索用ファイルquery.phpファイルをquery02.phpファイルとします。インクルードファイルcommon_bbs1.phpは上記改造を加えた上でcommon_bbs2a.phpとします。

 なお、インクルードファイルsystem02a.php内に以下の定数を定義し、使用することとします。

system02a.php

<?php
define(COMMON_BBS_FILE,"common_bbs2a.php");
define(MAIN_FILE,"main02a.php");
define(QUERY_FILE,"query02.php");
define(MATCH_URL,"/^http(s?)\:\/\/[\w\.\-\/\?\&\+\=\:\@\%\#]+$/");
?>

 

main02a.php

<?php
include "system02a.php";
include "common.php";
define(THIS_FILE,MAIN_FILE);
include COMMON_BBS_FILE;

$str_charset = "UTF-8";
// ページサイズ
$page_size = 5;
?>
-----(略)-----
?>
<!-- 「記事入力」、「全記事表示」のハイパーリンクの表示 -->
<p class="ac">
<a href="<?=MAIN_FILE?>">記事入力</a> | 
<a href="<?=MAIN_FILE?>?page=all">全記事表示</a><br><br>

<!-- 検索キーワード入力部の表示 -->
<form action="<?=QUERY_FILE?>" method="post">
<input type="text" name="keyword">
<input type="submit" name="command" value="検索">
</form>
</p>
<?php
-----(略)-----

 // 「送信」の場合
 elseif($_POST['command'] == "送信")
 {
  // 受信データが「空」でないかどうかチェック
  $str_error_message = data_check($str_name,$str_title,$str_message
                  ,$str_url);
-----(略)-----

  // データのテーブルへの保存
  $str_sql = "insert into tbl_bbs2 "
       . "(message_id,name,title,message,date,url)"
       . "values("
       . $new_id. ",'" . $str_name . "','" . $str_title
       . "','" . $str_message . "','" . $str_date
       . "','" . $str_url . "');";

  mysql_query($str_sql,$db);

  // データのリセット
  $new_id = "";
  $str_name = "";
  $str_title = "";
  $str_message = "";
  $str_date = "";
  $str_url = "";
-----(略)-----

(4)URLデータの表示

 インクルードファイルcommon_bbs2a.php内のユーザ定義関数page_disp()関数とmessage_disp()関数を以下のように改造します。

// ----------------------------------------------
// ページ単位表示
function page_disp($str_sql,$page,$page_size,$db)
{
-----(略)-----
 // ページ内全記事の表示
 while($arr_record = mysql_fetch_assoc($rs))
 {
  // 記事データの配列への格納
  $arr_message        = array();
  $arr_message['id']     = $arr_record['message_id'];
  $arr_message['name']   = $arr_record['name'];
  $arr_message['title']    = $arr_record['title'];
  $arr_message['message'] = $arr_record['message'];
  $arr_message['date']    = $arr_record['date'];
  $arr_message['url']  = $arr_record['url'];

  // 1個の記事本文の表示
  message_disp($arr_message);
  print "<br>\n";
 }
-----(略)-----
}

// -----------------------------------------------
// 1個の記事本文の表示
function message_disp(&$arr_message)
{
/*
$arr_message['id'] :記事番号
$arr_message['name'] :投稿者氏名
$arr_message['title'] :記事タイトル
$arr_message['message'] :記事本文
$arr_message['date'] :投稿日時
$arr_message['url'] :関連URL
*/
 $str_url = $arr_message['url'];
?>
<table class="bd_w1 bd_solid bd_b
         padding3 bd_spacing0 bd_collapse w600">
<tr class="b_dcdcdc xs">
 <td>No.<?=$arr_message['id']?> <?=$arr_message['title']?>
    <span class="fbold">[<?=$arr_message['name']?>] </span>
    <span class="696969"><?=$arr_message['date']?></span></td>
</tr>
<tr class="b_w xs">
 <td><?=$arr_message['message']?>
<?php
 if($str_url != "")
 {
?>
<br>URL: <a href="<?=$str_url?>"><?=$str_url?></a></td>
<?php
 }
?>
</tr>
</table>
<?php
}

ダウンロード(common_bbs2a.zip) ダウンロード(main02a.zip)

 main02a.phpにアクセスし、URLを記入した例を以下に示します。

 「送信」ボタンをクリックすると、URLもデータベースに保存され、下記のように、URLがハイパーリンク化され表示されます。

■削除可能なBBS

 投稿した記事を、後で投稿者が削除できるようなBBSを作成します。そのために記事を投稿するときに、パスワードも一緒に登録するようにします。記事を一覧表示した画面で、各記事に「削除」用リンクを表示し、「削除」用リンクをクリックすると、その記事を再表示するとともにパスワード入力欄も表示し、パスワードが入力され「削除」ボタンがクリックされると、当該記事を削除することとします。パスワードが登録されていない(パスワード欄が空)記事は削除できないこととします。また、パスワードは、セキュリティ上暗号化して保存しておくこととします。

(1)記事入力フォームへのパスワードの入力欄の追加

  記事入力フォームへのパスワードの入力欄を追加します。そこで、インクルードファイルcommon_bbs2a.phpの中の入力フォーム表示用のユーザ定義関数「input_form_disp()」を以下のように改造します。パスワード入力欄では、自動的に半角英数字入力モードにします。具体的には、スタイルシートの「hankaku」クラスを指定します。

// ----------------------------------------------
// 入力フォームの表示
function input_form_disp(&$str_name,&$str_title,&$str_message,&$str_url,&$str_pwd)
{
/*
$str_name   :投稿者氏名
$str_title    :記事タイトル
$str_message :記事本文
$str_url     :関連URL
$str_pwd    :パスワード
*/
 // 改行タグの改行コードへの変換
 $str_message = tag_entity_form($str_message);

 // URL欄の初期値設定
 if($str_url == "")
 {
  $str_url = "http://";
 }
?>
<table border="0">
<form method="post" action='<?=MAIN_FILE?>'>
<tr>
-----(略)-----
<tr>
 <td>URL</td><td><input name="url" size="60"
                 value="<?=$str_url?>"></td>
</tr>
<tr>
 <td>パスワード</td>
 <td><input type="password" name="pwd" size="8"
        class="hankaku"  value="<?=$str_pwd?>"></td>
</tr>

<tr>
 <td> </td><td><input type=submit name="command" value="送信"></td>
</tr>
</form>
</table>
<?php
}

(2)受信パスワードのチェック

 ここでは、パスワードは半角英数字のみで構成されることとします。つまり、パスワード文字列$str_pwdは、以下の正規表現に一致する必要があります。

preg_match("/[a-z][A-Z][0-9]/",$str_pwd);

 サンプルスクリプトでは、一致すべき正規表現パターンを定数MATCH_PWDとして、インクルードファイルsystem02b.php内に定義して使用することとします。

system02b.php

<?php
define(COMMON_BBS_FILE,"common_bbs2b.php");
define(MAIN_FILE,"main02b.php");
define(QUERY_FILE,"query02.php");
define(MATCH_URL,"/^http(s?)\:\/\/[\w\.\-\/\?\&\+\=\:\@\%\#]+$/");
define(MATCH_PWD,"/^[a-zA-Z0-9]+$/");
define(SALT,"bbs");
?>

この定数MATCH_PWDを使用して、インクルードファイルcommon_bbs2a.phpの中の受信データチェック用のユーザ定義関数「data_check()」を以下のように改造します。

// ----------------------------------------------
// 受信データのチェック
function data_check(&$str_name,&$str_title,&$str_message,&$str_url
             ,&$str_pwd)
{
/*
$str_name :投稿者氏名
$str_title :記事タイトル
$str_message :記事本文
$str_url :関連URL
$str_pwd :パスワード
*/
 global $str_charset;
 // データの受信
 $str_name = $_POST['name'];
 $str_title = $_POST['title'];
 $str_message = $_POST['message'];
 $str_url = $_POST['url'];
 $str_pwd = $_POST['pwd'];

 $str_name = tag_entity_input($str_name,$str_charset);
 $str_title = tag_entity_input($str_title,$str_charset);
 $str_message = tag_entity_input($str_message,$str_charset);

 // 文字列の前後の半角スペースを削除し、半角カタカナを全角カタカナに変換
 $str_name = input_str_convert($str_name);
 $str_title = input_str_convert($str_title);
 $str_message = input_str_convert($str_message);
 $str_pwd = trim($str_pwd);

  // 文字列が空かいなかのチェック
 if($str_name == "")
 {
 -----(略)-----
 elseif($str_pwd != "" && !preg_match(MATCH_PWD,$str_pwd))
 {
  $str = "パスワードを正しく記入してください";
 }

 elseif($str_url == "http://")
 {
  $str_url = "";
 }
 return $str;
}

(3)受信パスワードの暗号化と保存

 受信パスワードは、セキュリティ上、暗号化して保存することとします。暗号化は組み込み関数のcrypt()関数を使います。

暗号化パスワード = crypt(パスワード,キー文字列)

 キー文字列は、省略可能ですが、ここでは「bbs」という文字列を明示的に使うこととします。同じパスワードを同じキー文字列で暗号化すると暗号化されたパスワードも同じになります。ただ、暗号化されたパスワードからパスワードを再現することはほぼ不可能です。なお、キー文字列は定数SALTとして、system02b.phpファイル上で定義しておくこととします。

system02b.php

<?php
define(COMMON_BBS_FILE,"common_bbs2b.php");
define(MAIN_FILE,"main02b.php");
define(QUERY_FILE,"query02.php");
define(MATCH_URL,"/^http(s?)\:\/\/[\w\.\-\/\?\&\+\=\:\@\%\#]+$/");
define(MATCH_PWD,"/[a-z][A-Z][0-9]/");
define(SALT,"bbs");
?>

 main02a.phpファイルは、パスワードを暗号化し保存するように以下のように改造します。改造後のファイルをmain02b.phpとします。インクルードファイルcomon_bss2a.phpファイルは、上記改造を加えた後common_bbs2b.phpとします。

main02b.php

 -----(略)-----
 }
 // 「送信」の場合
 elseif($_POST['command'] == "送信")
 {
  // 受信データが「空」でないかどうかチェック
  $str_error_message = data_check($str_name,$str_title,$str_message
                       ,$str_url,$str_pwd);
  -----(略)-----
   // パスワードの暗号化
  $enc_pwd = "";
  if($str_pwd != "")
  {
   $enc_pwd = crypt($str_pwd,SALT);
  }

  // データのテーブルへの保存
  $str_sql = "insert into tbl_bbs2 "
        . "(message_id,name,title,message,date,url,pwd)"
        . "values("
        . $new_id. ",'" . $str_name . "','" . $str_title
        . "','" . $str_message . "','" . $str_date
        . "','" . $str_url . "','" . $enc_pwd . "');";
  -----(略)-----

(4)記事の一覧表示に「削除」リンク表示

 記事を一覧表示する画面で、個々の記事に「削除」リンクを表示するようにします。

 そこで、インクルードファイルcommon_bbs2b.php内のユーザ定義関数message_disp()関数を以下のように改造します。「削除」リンクをクリックしたときは、「EDIT_FILE」ファイルを起動することとします。定数「EDIT_FILE」の値は、後にインクルードファイルsyste02b.php内で定義することとします。

// -----------------------------------------------
// 1個の記事本文の表示
function message_disp(&$arr_message)
{
-----(略)-----
 $str_url_del = EDIT_FILE . "?id=" . $arr_message['id']
         . "&command=del";

?>
<table class="bd_w1 bd_solid bd_b
         padding3 bd_spacing0 bd_collapse w600">
-----(略)-----
</table>
<table class="bd_w0 w600">
<tr class="xs">
 <td class="ar"><a href="<?=$str_url_del?>">削除</a></td>
</tr>
</table>

(5)削除確認画面の表示

 個々の記事の「削除」リンクをクリックした後、当該記事を再確認のために再表示し、パスワードを記入し、「削除」ボタンをクリックすれば、削除を実行し、「キャンセル」ボタンをクリックすれば削除しないで、全記事表示に戻るようにします。

 サンプルリストを以下のedit02b.phpファイルに示します。

edit02b.php

<?php
include "system02b.php";
include "common.php";
define(THIS_FILE,EDIT_FILE);
include COMMON_BBS_FILE;
$str_charset = "UTF-8";
// ページサイズ
$page_size = 5;
?>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" >
<title>BBS2</title>
<meta http-equiv="Content-Style-Type" content="text/css">
<link rel="stylesheet" type="text/css" href="common.css">
</head>
<body class="b_ffff99">
<?php
 // データベースへの接続と選択
 $db = mysql_connect('localhost','webapl','pass1234');
 $db_name = "db_bbs";
 mysql_select_db($db_name,$db) or die("データベースがありません");
?>
<!-- 「記事入力」、「全記事表示」のハイパーリンクの表示 -->
<p class="ac">
<a href="<?=MAIN_FILE?>">記事入力</a> | 
<a href="<?=MAIN_FILE?>?page=all">全記事表示</a><br><br>
</p>
<?php
 // 「削除」リンクをクリックした場合
 if($_GET['command'] == "del")
 {
  // 記事番号の受信
  $message_id = $_GET['id'];

  if($message_id > 0)
  {
   // 当該記事の検索
   $str_sql = "select * from tbl_bbs2"
        . " where message_id = {$message_id};";
   $rs = mysql_query($str_sql,$db);

   if(mysql_num_rows($rs) === 1)
   {
    $arr_record = mysql_fetch_assoc($rs);

    // 記事データの配列への格納
    $arr_message = array();
    $arr_message['id']    = $arr_record['message_id'];
    $arr_message['name']   = $arr_record['name'];
    $arr_message['title']  = $arr_record['title'];
    $arr_message['message'] = $arr_record['message'];
    $arr_message['date']   = $arr_record['date'];
    $arr_message['url']   = $arr_record['url'];

    print "<p class='ac'>";
    print "パスワードを記入し、「削除」ボタンをクリックしてください<br>\n";
    // 1個の記事本文の表示
    message_show($arr_message);

    $message_id = $arr_message['id'];
    print "<form action='<?=THIS_FILE?>' method='post'>\n";
    print "パスワード<input type='password' name='pwd'>\n";
    print "<input type='hidden' name='id' value='{$message_id}'>\n";
    print "<input type='submit' name='command' value='削除'>\n";
    print "<input type='submit' name='command' value='キャンセル'>\n";
    print "</form>\n";
    print "</p>\n";
    print "<br>\n";

   }
   mysql_free_result($rs);
  }
 }
 mysql_close($db);

?>

 なお、確認のために、 当該記事を表示するユーザ定義関数message_show()をインクルードファイルcommon_bbs02b.php内に作成します。

// -----------------------------------------------
// 1個の記事本文の表示(確認用)
function message_show(&$arr_message)
{
/*
$arr_message['id'] :記事番号
$arr_message['name'] :投稿者氏名
$arr_message['title'] :記事タイトル
$arr_message['message'] :記事本文
$arr_message['date'] :投稿日時
$arr_message['url'] :関連URL
*/
 $str_url = $arr_message['url'];

 $str_url_del = EDIT_FILE . "?id=" . $arr_message['id']
        . "&command=del";
?>
<table class="bd_w1 bd_solid bd_b
       padding3 bd_spacing0 bd_collapse w600">
<tr class="b_dcdcdc xs">
 <td>No.<?=$arr_message['id']?> <?=$arr_message['title']?>
   <span class="fbold">[<?=$arr_message['name']?>] </span>
   <span class="696969"><?=$arr_message['date']?></span></td>
</tr>
<tr class="b_w xs">
 <td><?=$arr_message['message']?>
<?php
 if($str_url != "")
 {
?>
<br>URL: <a href="<?=$str_url?>"><?=$str_url?></a></td>
<?php
 }
?>
</tr>
</table>
<?php
}

(6)指定記事の削除の実行

 (5)の削除確認画面で「削除」ボタンをクリックすると、「EDIT_FILE」ファイル(ここではedit02b.phpファイル)が起動され、POSTメソッドで$_POST['command']に「削除」が受信されています。また、同様にPOSTメソッドで記事番号とパスワードも受信されますから、以下のようにSQLのdelete文により指定記事を削除します。

delete from tbl_bbs2 where message_id = 記事番号 and pwd = '暗号化パスワード';

 なお、パスワードの暗号化にあたっては、記事を投稿したときと同じ暗号化用キーを使って暗号化します。ここではその暗号化キーは定数SALTに設定されています。

 パスワード等が間違っていて記事が削除できなかった場合は、「戻る」ボタンをクリックすると、ブラウザのヒストリ(履歴)で一つ前のページに戻るようにします。そのために、以下のjavascriptのメソッドを使います。

onClick='history.back()'

 サンプルリストをedit02b.phpファイルに以下のように追加します。

edit02b.php

-----(略)-----

 // 「削除」実行の場合
 elseif($_POST['command'] == "削除")
 {
  // データの受信
  $message_id = $_POST['id'];
  $str_pwd   = $_POST['pwd'];

  $str_pwd  = trim($str_pwd);
  print "<p class='ac'>\n";
  if(preg_match(MATCH_PWD,$str_pwd))
  {
   // パスワードの暗号化
   $enc_pwd = "";
   if($str_pwd != "")
   {
    $enc_pwd = crypt($str_pwd,SALT);
   } 
   // 削除用SQL文
   $str_sql = "delete from tbl_bbs2 "
        . "where message_id = {$message_id} and pwd = '{$enc_pwd}';";

   $rs = mysql_query($str_sql,$db);
   // 削除されたレコード数の取得
   $del_rows = mysql_affected_rows($db);

   if($del_rows > 0)
   {
    print "記事を削除しました。<br><br>\n";
   }
   else
   {
    print "記事は削除できませんでした。<br><br>\n";
    print "<input type='button' value='戻る' "
      . "onclick='history.back()'><br>\n";
   }
  }
  else
  {
   print "記事は削除できませんでした。<br><br>\n";
   print "<input type='button' value='戻る' "
         . "onClick='history.back()'><br>\n";
  }
  print "</p>\n";
 }

ダウンロード(common_bbs2b.zip) ダウンロード(edit02b.zip) 
ダウンロード(main02b.php)     ダウンロード(system02b.sip)

 main02b.phpファイルにアクセスし、記事を記入し、「送信」ボタンをクリックします。削除用パスワードも記入します。

 記事が表示され、記事の右下に削除用のリンクが表示されます。

 削除用リンクをクリックすると、削除確認画面が表示されます。

 記事を投稿したときのパスワードを記入し、「削除」ボタンをクリックします。

 記事が削除された旨を示す画面が表示されます。「全記事表示」画面に戻ります。

 記事が削除されたことが確認されます。

■更新可能なBBS

  投稿した記事を、後で投稿者が更新できるようなBBSを作成します。そのために記事を投稿するときに、パスワードも一緒に登録するようにします。記事を一覧表示した画面で、各記事に「更新」用リンクを表示し、「更新」用リンクをクリックすると、その記事を再表示するとともにパスワード入力欄も表示し、パスワードが入力され「更新」ボタンがクリックされると、当該記事を更新モードで再表示することとします。パスワードが登録されていない(パスワード欄が空)記事は更新できないこととします。また、パスワードは、上記「削除可能なBBS」で使用したものと同じパスワードを使用することとします。

 更新モードで再表示された記事本文を更新し、「更新」ボタンをクリックすると、再確認のために記事を再表示し、「送信」ボタンがクリックされると登録し、「キャンセル」ボタンがクリックされると、更新モード画面に戻ることとします。

(1)記事の一覧表示に「更新」リンク表示

 記事を一覧表示する画面で、個々の記事に「更新」リンクを表示するようにします。

 そこで、インクルードファイルcommon_bbs2b.php内のユーザ定義関数message_disp()関数を以下のように改造します。「編集」リンクをクリックしたときは、「EDIT_FILE」ファイルを起動することとします。定数「EDIT_FILE」の値は、後にインクルードファイルsystem02c.php内で定義することとします。

common_bbs2c.php

// -----------------------------------------------
// 1個の記事本文の表示
function message_disp(&$arr_message)
{
 -----(略)------
 // 「削除」用URL
 $str_url_del = EDIT_FILE . "?id=" . $arr_message['id']
         . "&command=del";
 // 「更新」用URL
 $str_url_update = EDIT_FILE . "?id=" . $arr_message['id']
            . "&command=update";

?>
 -----(略)------
<table class="bd_w0 w600">
<tr class="xs">
<td class="ar"><a href="<?=$str_url_del?>">削除</a>
          <a href="<?=$str_url_update?>">更新</a></td>
</tr>
</table>
<?php
}

(2)更新確認画面の表示

 個々の記事の「更新」リンクをクリックした後、当該記事を再確認のために再表示し、パスワードを記入し、「更新」ボタンをクリックすれば、更新モードで当該記事を再表示し、「戻る」ボタンをクリックすれば、全記事表示に戻るようにします。

 edit02b.phpファイルを改造したサンプルリストを以下のedit02c.phpに示します。「削除」リンクをクリックした場合の処理とほぼ同じ処理です。

edit02c.php

<?php
include "system02c.php";
include "common.php";

-----(略)------

 // 「更新」リンクをクリックした場合
 if($_GET['command'] == "update")
 {
  // 記事番号の受信
  $message_id = $_GET['id'];
  if($message_id > 0)
  {
   // 当該記事の検索
   $str_sql = "select * from tbl_bbs2"
         . " where message_id = {$message_id};";
   $rs = mysql_query($str_sql,$db);
   if(mysql_num_rows($rs) === 1)
   {
    $arr_record = mysql_fetch_assoc($rs);

    // 記事データの配列への格納
    $arr_message = array();
    $arr_message['id']        = $arr_record['message_id'];
    $arr_message['name']      = $arr_record['name'];
    $arr_message['title']      = $arr_record['title'];
    $arr_message['message']   = $arr_record['message'];
    $arr_message['date']      = $arr_record['date'];
    $arr_message['url']       = $arr_record['url'];

    print "<p class='ac'>";
    print "パスワードを記入し、「更新」ボタンをクリックしてください<br>\n";
    // 1個の記事本文の表示
    message_show($arr_message);
    $message_id = $arr_message['id'];
    print "<form action='" . THIS_FILE . "' method='post'>\n";
    print "パスワード<input type='password' name='pwd'>\n";
    print "<input type='hidden' name='id' value='{$message_id}'>\n";
    print "<input type='submit' name='command' value='更新'>\n";
    print "<input type='button' value=戻る' "
               . "onClick='history.back()'>\n";
    print "</form>\n";
    print "</p>\n";
    print "<br>\n";
   }
   mysql_free_result($rs);
 }
}

(3)更新モードでの記事画面の表示

 更新確認画面でパスワードが記入され、「更新」ボタンがクリックされると、、「EDIT_FILE」ファイル(ここではedit02c.phpファイル)が起動され、POSTメソッドで$_POST['command']に「更新」が受信されています。また、同様にPOSTメソッドで記事番号とパスワードも受信されますから、以下のようにSQLのselect文により指定記事を検索します。

select * from tbl_bbs2 where message_id = 記事番号 and pwd = '暗号化パスワード'


 1個の記事が検索されれば、パスワードも正しかったということで、当該記事の更新画面を表示します。

 当該記事の更新画面の表示のために、組み込み関数update_form_disp()を新たに定義します。update_form_disp()関数は、既存のinput_form_disp()を若干改造したものになります。update_form_disp()関数はインクルードファイルcommon_bbs2b.phpに追加することとし、ファイル名を新たにcommon_bbs2c.phpとします。

edit02c.php

<?php
include "system02c.php";
include "common.php";

-----(略)------

 // 「更新」実行の場合
 elseif($_POST['command'] == "更新")
 {
  // データの受信
  $message_id = $_POST['id'];
  $str_pwd = $_POST['pwd'];

  $str_pwd = trim($str_pwd);
  if(preg_match(MATCH_PWD,$str_pwd))
  {
   // パスワードの暗号化
   $enc_pwd = "";
   if($str_pwd != "")
   {
    $enc_pwd = crypt($str_pwd,SALT);
    // 更新用SQL文
    $str_sql = "select * from tbl_bbs2 "
          . "where message_id = {$message_id} and pwd = '{$enc_pwd}';";
    $rs = mysql_query($str_sql,$db);

    // 検索されたレコード数の取得
    $select_rows = mysql_num_rows($db);
    if($select_rows > 0)

    {
     // 検索結果リソースの連想配列への格納
     $arr_record = mysql_fetch_assoc($rs);
     // 記事データの変数への格納
     $str_name   = $arr_record['name'];
     $str_title    = $arr_record['title'];
     $str_message = $arr_record['message'];
     $str_date    = $arr_record['date'];
     $str_url     = $arr_record['url'];
     $str_update   = $arr_record['date_update'];
     // 記事更新画面の表示
     update_form_disp($message_id,$str_name,$str_title,$str_message
                ,$str_date,$str_update,$str_url,$str_pwd);

    }
    else
    {
     print "記事は更新できません。<br><br>\n";
     print "<input type='button' value='戻る' "
           . "onclick='history.back()'><br>\n";
    }
    print "記事は更新できません。<br><br>\n";
    print "<input type='button' value='戻る' "
           . "onclick='history.back()'><br>\n";
   }
  }
  else
  {
   print "記事は更新できません。<br><br>\n";
   print "<input type='button' value='戻る' "
          . "onClick='history.back()'><br>\n";
  }
 }

common_bbs2c.php

// ----------------------------------------------
// 更新モードでの記事の表示
function update_form_disp($message_id,$str_name,$str_title,$str_message
                 ,$str_date,$str_update,$str_url,$str_pwd)
{

/*
$str_name :投稿者氏名
$str_title :記事タイトル
$str_message :記事本文
$str_url :関連URL
$str_pwd :パスワード
*/
 // 改行タグの改行コードへの変換
 $str_message = tag_entity_form($str_message);

 // URL欄の初期値設定
 if($str_url == "")
 {
  $str_url = "http://";
 }
?>
<table border="0">
<form method="post" action='<?=EDIT_FILE?>'>
<tr>
 <td> </td><td>BBS1</td>
</tr>
<tr>
 <td>記事番号</td><td><?=$message_id?></td>
</tr>
<tr>
 <td>氏名</td><td><input name="name" size="30"
                 value="<?=$str_name?>"></td>
</tr>
<tr>
 <td>タイトル</td><td><input name="title" size="60"
                   value="<?=$str_title?>"></td>
</tr>
<tr>
 <td>記事</td>
 <td><textarea name="message"
          rows="5" cols="60"><?=$str_message?></textarea></td>
</tr>
<tr>
 <td>URL</td><td><input name="url" size="60"
                 value="<?=$str_url?>"></td>
</tr>
<tr>
 <td>パスワード</td>
 <td><input type="password" name="pwd" size="8"
        class="hankaku" value="<?=$str_pwd?>">(半角英数字)</td>
</tr>
<tr>
 <td>投稿日</td><td><?=$str_date?></td>
</tr>
<tr>
 <td class='xs'>前回更新日</td><td><?=$str_update?></td>
</tr>
<tr>
 <td> </td>
 <td><input type="submit" name="command" value="送信">
    <input type="submit" name="command" value="キャンセル"></td>
</tr>
 <input type="hidden" name="id" value="<?=$message_id?>">
 <input type="hidden" name="date" value="<?=$str_date?>">
 <input type="hidden" name="update" value="<?=$str_update?>">
</form>
</table>
<?php
}

 

(4)更新結果の確認画面の表示

 記事更新画面で、「送信」ボタンがクリックされると、EDIT_FILEファイル(ここではedit02c.phpファイル)が起動され、POSTメソッドで$_POST['command']に「送信」が受信されます。

 受信データを新規の記事投稿の場合と同様ユーザ定義関数data_check()関数でチェックします。

 受信データが正しければ、確認のために更新後の記事を表示します。

 記事を確認後、正しければ「OK」ボタンをクリックし、正しくなければ「戻る」ボタンでブラウザの前のページに戻るようにします。

 サンプルリストを以下に示します。以下のリストはedit02c.phpファイルに追加します。

edit02c.php

-----(略)-----

 // 「送信」の場合
 elseif($_POST['command'] == "送信")
 {
  // 受信データのチェック
  $str_error_message = data_check($str_name,$str_title,$str_message
                       ,$str_url,$str_pwd);
  if($str_error_message == "")
  {
   // 記事データの配列への格納
   $message_id  = $_POST['id'];
   $str_date   = $_POST['date'];
   $str_update  = $_POST['update'];

   $arr_message = array();
   $arr_message['id']      = $message_id;
   $arr_message['name']    = $str_name;
   $arr_message['title']    = $str_title;
   $arr_message['message'] = $str_message;
   $arr_message['date']    = $str_date;
   $arr_message['url']     = $str_url;

   print "内容を確認し、「OK」ボタンをクリックしてください<br>\n";
   // 1個の記事本文の表示
   message_show($arr_message);

   // 改行タグの改行コードへの変換
   $str_message = tag_entity_form($str_message);
   if($str_url == "")
   {
    $str_url = "http://";
   }

   print "<form action='" . THIS_FILE . "' method='post'>\n";
   print "<input type='hidden' name='id' value='{$message_id}'>\n";
   print "<input type='hidden' name='name' value='{$str_name}'>\n";
   print "<input type='hidden' name='title' value='{$str_title}'>\n";
   print "<input type='hidden' name='message' value='{$str_message}'>\n";
   print "<input type='hidden' name='url' value='{$str_url}'>\n";
   print "<input type='hidden' name='pwd' value='{$str_pwd}'>\n";
   print "<input type='submit' name='command' value='OK'>\n";
   print "<input type='button' value='戻る' "
           . "onClick='history.back()'>\n";
   print "</form>\n";
   print "<br>\n";
 }
}

(5)更新記事の保存

 更新結果の確認画面で、「OK」ボタンをクリックするとEDIT_FILEファイル(ここではedit02c.phpファイル)が起動され、POSTメソッドで$_POST['command']に「OK」が受信されます。

 ユーザ定義関数data_check()で、再度受信データをチェックし、正常であれば記事番号も受信し、更新日を設定します。

 パスワードが設定されていれば、以下のようにSQLのupdate文で記事データの更新を行います。

update tbl_bbs2 set フィールド名1 = 値1,
              フィールド名2 = 値2,
             ----------------
          where message_id = 記事番号;

 サンプルリストを以下に示します。以下のリストは、edit02c.phpに追加します。

edit02c.php

-----(略)-----

 // 「OK」の場合
 elseif($_POST['command'] == "OK")
 {
  // 受信データのチェック
  $str_error_message = data_check($str_name,$str_title,$str_message
                       ,$str_url,$str_pwd);
  if($str_error_message == "")
  {
   // データの受信
   $message_id = $_POST['id'];
   // 現在日時の取得
   $str_update = date("Y-m-d H:i:s",time());

   $str_name   = mysql_real_escape_string($str_name);
   $str_title    = mysql_real_escape_string($str_title);
   $str_message = mysql_real_escape_string($str_message);

    if($str_pwd !="")
   {
    // パスワードの暗号化
    $enc_pwd = crypt($str_pwd,SALT);
    // データのテーブルへの保存
    $str_sql = "update tbl_bbs2 "
          . "set name = '" . $str_name . "',"
          . " title = '" . $str_title . "',"
          . " message = '" . $str_message . "',"
          . "date_update = '" . $str_update . "',"
          . " url = '" . $str_url . "',"
          . " pwd = '" . $enc_pwd . "'"
          . " where message_id = " . $message_id . ";";


    if(!mysql_query($str_sql,$db))
   {
    print "<br>ERROR_NO=" . mysql_errno($db) . ":"
                     . mysql_error($db) . "<br>}";
   }
  }
  // テーブルのデータの一覧取得(最後に「;」をつけない)
  $str_sql = "select * from tbl_bbs2 order by message_id desc";

   // 第1ページ目の設定
  $page = 1;

   // ページ単位表示
  page_disp($str_sql,$page,$page_size,$db);

   $db = mysql_close($db);
 }
 else
 {
  print "<font style='color:red'>{$str_error_message}</font><br>\n";
  // 更新画面の再表示
  update_form_disp($message_id,$str_name,$str_title,$str_message
             ,$str_date,$str_update,$str_url,$str_pwd);
 }
}

ダウンロード(common_bbs2c.zip)  ダウンロード(edit02c.zip)
ダウンロード(main02c.zip)      ダウンロード(system02c.php)

 main02c.phpにアクセスします。個々の記事には、「更新」リンクが表示されています。2番目の記事の「更新」リンクをクリックします。

 更新確認画面が表示されます。記事投稿時に入力したパスワードを記入し、「更新」ボタンをクリックします。

 更新モードで記事が表示されます。必要な更新あるいは修正等を行います。ここでは、赤線で囲った部分を修正しています。

 パスワードは前のままでも、新たに入力しなおしてもいずれでもかまいません。「送信」ボタンをクリックします。

 更新結果の確認画面が表示されます。よければ「OK」ボタンをクリックします。

 正式に保存された結果が一覧表示されます。

■引用可能なBBS

 ある記事に対して、引用して返信できるBBSを制作します。記事を一覧表示した画面で、各記事に「返信」用リンクを表示し、「品進」用リンクをクリックすると、その記事を引用した形で記事入力画面を表示します。返信用記事のタイトルの冒頭に「Re[n]:」を付加することとします。nは最初は1で、Re[1]:への返信はRe[2]:としていきます。記事本文の引用部分は、各行の冒頭に「> 」を挿入することとします。

(1)記事の一覧表示に「返信」リンク表示

 記事を一覧表示する画面で、個々の記事に「返信」リンクを表示するようにします。

 そこで、インクルードファイルcommon_bbs2c.php内のユーザ定義関数message_disp()関数を以下のように改造します。「返信」リンクをクリックしたときは、「RESPONSE_FILE」ファイルを起動することとします。定数「RESPONSE_FILE」の値は、後にインクルードファイルsystem02d.php内で定義することとします。

common_bbs2d.php

-----(略)-----

// -----------------------------------------------
// 1個の記事本文の表示
function message_disp(&$arr_message)
{
-----(略)-----
 // 「更新」用URL
 $str_url_update = EDIT_FILE . "?id=" . $arr_message['id']
                   . "&command=update";
 // 「返信」用URL
 $str_url_response = RESPONSE_FILE . "?id=" . $arr_message['id']
                         . "&command=response";

?>
<table class="bd_w1 bd_solid bd_b
         padding3 bd_spacing0 bd_collapse w600">
<tr class="b_dcdcdc xs">
 <td>No.<?=$arr_message['id']?> <?=$arr_message['title']?>
     <span class="fbold">[<?=$arr_message['name']?>] </span>
     <span class="696969"><?=$arr_message['date']?></span></td>
 <td class='ar'><a href="<?=$str_url_response?>">返信</a></td>
</tr>
<tr class="b_w xs">
<td colspan=2><?=$arr_message['message']?>
<?php
-----(略)-----
}

(2)返信用記事入力フォームの表示

 「返信」用リンクがクリックされると、、「RESPONSE_FILE」ファイル(ここではresponse02d.phpファイル)が起動され、POSTメソッドで$_POST['command']に「response」が受信されています。また、同様にPOSTメソッドで記事番号も受信されますから、以下のようにSQLのselect文により指定記事を検索します。

select * from tbl_bbs2 where message_id = 記事番号'


 当該記事の返信画面の表示のために、ユーザ定義関数response_form_disp()を新たに定義し、上記インクルードファイルcommon_bbs2c.phpに追加しcommon_bbs2d.phpとします。

 「返信」用リンクがクリックされた場合の状態を、返信用記事入力前ということで、「$status="before"」とします。後に、返信用記事入力後に「送信」ボタンをクリックした場合の状態は、「$status="before"」とします。

 response02d.phpで、「返信」用リンクがクリックされた場合のサンプルリストを以下に示します。

response02d.php

<?php
include "system02d.php";
include "common.php";
define(THIS_FILE,RESPONSE_FILE);
include COMMON_BBS_FILE;

-----(略)-----

 // 「返信」リンクをクリックした場合
 if($_GET['command'] == "response")
 {
  $status = "before";

  // データの受信
  $parent_id = $_GET['id'];
  // 検索用SQL文
  $str_sql = "select * from tbl_bbs2 "
        . "where message_id = {$parent_id} ;";
  $rs = mysql_query($str_sql,$db);
  // 検索されたレコード数の取得
  $select_rows = mysql_num_rows($rs);
  if($select_rows > 0)
  {
   // 検索結果リソースの連想配列への格納
   $arr_record = mysql_fetch_assoc($rs);

   // 記事データの変数への格納
   $str_title = $arr_record['title'];
   $str_message = $arr_record['message'];

   // 記事返信画面の表示
   response_form_disp($status,$parent_id,$str_name,$str_title
                    ,$str_message,$str_url,$str_pwd);

  }
  else
  {
   print "記事番号が間違っています。<br><br>\n";
   print "<input type='button' value='戻る' "
           . "onClick='history.back()'><br>\n";
  }
 }

 「$status="before"」の場合は、@タイトルの冒頭に返信のレベルを示す文字列「Re[n]:」を挿入・置換します。この文字列を返信レベルカウンターと呼びます。「n」は返信レベルで、1,2,3と増加させます。この返信レベルカウンターを挿入・置換するためにユーザ定義関数re_counter()関数を作成し、使用します。また、A記事本文の行頭に引用記号「> 」を挿入します。

common_bbs2d.php

// ----------------------------------------------
// 返信フォームの表示
function response_form_disp($status,$parent_id,$str_name,$str_title
                       ,$str_message,$str_url,$str_pwd)

{
/*
$parent_id :親記事番号
$str_name :投稿者氏名
$str_title :記事タイトル
$str_message :記事本文
$str_url :関連URL
$str_pwd :パスワード
*/
 // 改行タグの改行コードへの変換
 $str_message = tag_entity_form($str_message);

 if($status == "before")
 {
  // タイトルの冒頭に「Re[n]:」を付加する
  $str_title = re_counter($str_title);

  // 記事本文の行頭に引用記号「> 」を挿入する
  $arr_message = array();
  $arr_message = explode("\n",$str_message);
  $arr_message_new = array();
  foreach($arr_message as $str_line)
  {
   $str_line = "&gt; " . $str_line;
   array_push($arr_message_new,$str_line);
  }
  $str_message = implode("\n",$arr_message_new);

 }

 // URL欄の初期値設定
 if($str_url == "")
 {
  $str_url = "http://";
 }
?>
<table border="0">
<form method="post" action='<?=RESPONSE_FILE?>'>
<tr>
 <td> </td><td>BBS1</td>
</tr>
<tr>
 <td>氏名</td><td><input name="name" size="30"
                 value="<?=$str_name?>"></td>
</tr>
<tr>
 <td>タイトル</td><td><input name="title" size="60"
                   value="<?=$str_title?>"></td>
</tr>
<tr>
 <td>記事</td>
 <td><textarea name="message"
          rows="5" cols="60"><?=$str_message?></textarea></td>
</tr>
<tr>
 <td>URL</td><td><input name="url" size="60"
                 value="<?=$str_url?>"></td>
</tr>
<tr>
 <td>パスワード</td>
 <td><input type="password" name="pwd" size="8"
        class="hankaku" value="<?=$str_pwd?>">(半角英数字)</td>
</tr>
<tr>
 <td> </td><td><input type=submit name="command" value="送信"></td>
</tr>
<input type="hidden" name="parent_id" value="<?=$parent_id?>">
</form>
</table>
<?php
}

-----(略)-----

// ----------------------------------------------
// タイトルの冒頭に返信レベルカウンター「Re[n]:」を付加する
function re_counter($str)
{
 // 返信レベルカウンター用文字列の設定
 $str_re1 = "Re[";
 $str_re2 = "]:";
 // 返信レベルカウンターのパターンマッチ
 if(preg_match(MATCH_RE,$str,$arr))
 {
  // 返信レベルカウンターのレベル値を1だけ増分
  $str_re_next = $str_re1 . ($arr[2] + 1) . $str_re2;
  // 返信レベルカウンターの置換
  $str = preg_replace(MATCH_RE,$str_re_next,$str);
 }
 else
 // 返信レベルカウンターの文字列がない場合(最初の返信)
 {
  $str = $str_re1 . "1" . $str_re2 . $str;
 }
return $str;
}

 ユーザ定義関数re_counter()では、preg_match()関数で 返信レベルカウンターのパターンマッチを行います。パタンーンマッチ用の正規表現は「"/^(Re\[(\d+)\]:)/"」で、この文字列はsystem02d.php内で、定数「MATCH_RE」として定義しておきます。

preg_match("/^(Re\[(\d+)\]:)/",元の文字列,配列)

 preg_match()関数では、「( )」内のサブパターンに一致した文字列は、順次第3の引数の配列(ここでは$arr)に格納されます。サブパターン「Re[n]:」に一致した文字列は$arr[1]に格納され、サブパターン「n」に一致した数値は$arr[2]に格納されます。ここで、「n」は返信レベルを示す1桁以上の整数値です。「n」を「n+1」に1個増分し、再度返信レベルカウンター「Re[n+1]:」の文字列を作成し、preg_replace()関数で置換します。

preg_replace("/^(Re\[(\d+)\]:)/",置換文字列,元の文字列)

(3)返信用記事の保存

 返信記事記入画面で、「送信」ボタンがクリックされると、RESPONSE_FILEファイル(ここではresponse02d.phpファイル)が起動され、POSTメソッドで$_POST['command']に「送信」が受信されます。状態は、「$status = "after"」とします。また、親記事番号を受信します。

 受信データを新規の記事投稿の場合と同様ユーザ定義関数data_check()関数でチェックします。

 入力データが正しければ、新規記事入力の場合と同様SQLのinsert文で、記事データをデータベースに保存します。なお、ここでは、親記事番号も保存します。

 入力データが正しくなければ、返信記事入力画面をresponse_form_disp()関数で、再表示します。

response02d.php

-----(略) -----

 // 「送信」の場合
 elseif($_POST['command'] == "送信")
 {
  $status = "after";
  // 親記事番号の受信
  $parent_id = $_POST['parent_id'];

  // 受信データのチェック
  $str_error_message = data_check($str_name,$str_title,$str_message
                              ,$str_url,$str_pwd);

  if($str_error_message == "")
  {
   // 現在日時の取得
   $str_date = date("Y-m-d H:i:s",time());
   // 「message_id」の生成
   // tbl_bbs2テーブルのmessage_idの最大値の取得
   $str_sql = "select max(message_id) as max_id from tbl_bbs2;";
   $rs = mysql_query($str_sql,$db);
   $arr_record = array();
   $arr_record = mysql_fetch_assoc($rs);
   $max_id = $arr_record['max_id'];
   if($max_id > 0)
   {
    $new_id = $max_id + 1;
   }
   else
   {
    $new_id = 1;
   }
   // SQL文のためのエスケープ処理
   $str_name   = mysql_real_escape_string($str_name);
   $str_title    = mysql_real_escape_string($str_title);
   $str_message = mysql_real_escape_string($str_message);

   // パスワードの暗号化
   disp_var(2,$str_pwd,'$str_pwd');
   $enc_pwd = "";
   if($str_pwd != "")
   {
    $enc_pwd = crypt($str_pwd,SALT);
   }

   // データのテーブルへの保存
   $str_sql = "insert into tbl_bbs2 "
              . "(message_id,name,title,message,date,url,pwd,parent_id)"
              . "values("
              . $new_id. ",'" . $str_name . "','" . $str_title
              . "','" . $str_message . "','" . $str_date
              . "','" . $str_url . "','" . $enc_pwd
              . "'," . $parent_id . ");";
   if(!mysql_query($str_sql,$db))

   {
    print "<br>ERROR_NO=" . mysql_errno($db) . ":"
                    . mysql_error($db) . "<br>}";
   }

   // データのリセット
   $new_id = "";
   $str_name = "";
   $str_title = "";
   $str_message = "";
   $str_date = "";
   $str_url = "";
   $str_pwd = "";

   // テーブルのデータの一覧取得(最後に「;」をつけない)
   $str_sql = "select * from tbl_bbs2 order by message_id desc";

   // 第1ページ目の設定
   $page = 1;

   // ページ単位表示
   page_disp($str_sql,$page,$page_size,$db);
  }
  else
  {
   print "<span class='red'>{$str_error_message}</span><br>\n";
   // 記事返信画面の表示
   response_form_disp($status,$parent_id,$str_name,$str_title
                     ,$str_message,$str_url,$str_pwd);

  }
 }

system02d.php

<?php
define(COMMON_BBS_FILE,"common_bbs2d.php");
define(MAIN_FILE,"main02d.php");
define(QUERY_FILE,"query02.php");
define(EDIT_FILE,"edit02d.php");
define(RESPONSE_FILE,"response02d.php");
define(MATCH_URL,"/^http(s?)\:\/\/[\w\.\-\/\?\&\+\=\:\@\%\#]+$/");
define(MATCH_PWD,"/^[0-9a-zA-Z]+$/");
define(MATCH_RE, "/^(Re\[(\d+)\]:)/");
define(SALT,"bbs");
?>

 

ダウンロード(common_bbs2d.zip)   ダウンロード(main02d.zip)
ダウンロード(response02d.zip)     ダウンロード(system02d.php)

 main02d.phpファイルにアクセスし、返信したい記事の「返信」リンクをクリックします。

 タイトルの冒頭に、「Re[1]:」が挿入され、引用文の各行頭には「> 」が挿入されて表示されます。

 返信記事を入力し、「送信」ボタンをクリックします。

 返信記事が投稿されます。

■メールで返信可能なBBS

 投稿された記事に対して、メールでも返信可能なBBSを作成します。メールでも返信するかいなかは、ラジオボタンで選択可能とします。

(1)記事入力画面にメールアドレス記入欄を設けます。

 common_bbs2d.phpファイル内のinput_form_disp()関数をメールアドレス入力欄を表示するように以下のように改造します。改造後のファイル名をcommon_bbs2e.phpとします。

common_bbs2e.php

-----(略)-----

// ----------------------------------------------
// 入力フォームの表示
function input_form_disp(&$str_name,&$str_mail_address,&$str_title
,&$str_message,&$str_url,&$str_pwd)
{
-----(略)-----
?>
<table border="0">
<form method="post" action='<?=MAIN_FILE?>'>
<tr>
 <td> </td><td>BBS1</td>
</tr>
<tr>
 <td>氏名</td><td><input name="name" size="30"
             value="<?=$str_name?>"></td>
</tr>
<tr>
 <td>メール</td><td><input name="mail" size="60"
           class="hankaku" value="<?=$str_mail_address?>"></td>

</tr>
<tr>
 <td>タイトル</td><td><input name="title" size="60"
            value="<?=$str_title?>"></td>
</tr>
-----(略)-----
<?php
}

(2)受信メールアドレスのチェック

  受信したメールアドレスデータが、メールアドレスとして正しい文字列かどうか、セキュリティ対策上チェックする必要があります。

 メールアドレス文字列$str_mail_addressは、Perl互換の正規表現として、たとえば以下の正規表現に一致する必要があります。

preg_match("/^[\w\d\-\.]+\@[\w\d\-\.]+$/",$str_mail_address)

  サンプルスクリプトでは、一致すべき正規表現パターンを定数MATCH_MAILとして、インクルードファイルsystem02e.php内に定義して使用することとします。

sysytem02e.php

<?php
define(COMMON_BBS_FILE,"common_bbs2e.php");
define(MAIN_FILE,"main02e.php");
define(QUERY_FILE,"query02.php");
define(EDIT_FILE,"edit02e.php");
define(RESPONSE_FILE,"response02e.php");
define(MATCH_URL,"/^http(s?)\:\/\/[\w\.\-\/\?\&\+\=\:\@\%\#]+$/");
define(MATCH_PWD,"/^[0-9a-zA-Z]+$/");
define(MATCH_RE, "/^(Re\[(\d+)\]:)/");
define(MATCH_MAIL,"/^[\w\d\-\.]+\@[\w\d\-\.]+$/");
define(SALT,"bbs");
?>

 この定数MATCH_MAILを使用して、インクルードファイルcommon_bbs2e.phpの中の受信データチェック用のユーザ定義関数「data_check()」を以下のように改造します。

common_bbs2e.php

-----(略)-----

// ----------------------------------------------
// 受信データのチェック
function data_check(&$str_name,&$str_mail_address,&$str_title,&$str_message
,&$str_url,&$str_pwd)
{
/*
$str_name :投稿者氏名
$str_mail_address :メールアドレス
$str_title :記事タイトル
$str_message :記事本文
$str_url :関連URL
$str_pwd :パスワード
*/
 global $str_charset;
 // データの受信
 $str_name = $_POST['name'];
 $str_mail_address = $_POST['mail'];
 $str_title = $_POST['title'];

 -----(略)-----

 // 文字列の前後の半角スペースを削除
 $str_mail_adress = trim($str_mail_address);

 // 文字列が空かいなかのチェック
 if($str_name == "")
 {
  $str = "氏名を記入してください";
 }
 elseif($str_mail_address != ""
     && !preg_match(MATCH_MAIL,$str_mail_address))
 {
  $str = "メールアドレスを正しく記入してください";
 }

 elseif($str_title == "")

 -----(略)-----
}

(3)受信データの保存

 受信データの保存時も、メールアドレスを保存するように、main02d.phpを改造し、main02e.phpとします。

main02e.php

<?php
include "system02e.php";
include "common.php";
define(THIS_FILE,MAIN_FILE);
include COMMON_BBS_FILE;

 -----(略)-----

 // 「送信」の場合
 elseif($_POST['command'] == "送信")
 {
  // 受信データが「空」でないかどうかチェック
  $str_error_message = data_check($str_name,$str_mail_address,$str_title
                  ,$str_message,$str_url,$str_pwd);
  if($str_error_message == "")
  {
  -----(略)-----

   // データのテーブルへの保存
   $str_sql = "insert into tbl_bbs2 "
        . "(message_id,name,mail,title,message,date,url,pwd)"
        . "values("
        . $new_id. ",'" . $str_name . "','" .$str_mail_address
        . "','" . $str_title
        . "','" . $str_message . "','" . $str_date
        . "','" . $str_url . "','" . $enc_pwd . "');";
   if(!mysql_query($str_sql,$db))
   {
   -----(略)-----

   }
  }
  print "<p class='ac'>";

  // 入力フォームの表示
  input_form_disp($str_name,$str_mail_address,$str_title,$str_message
                   ,$str_url,$str_pwd);


(4)個々の記事に、メール用リンクを表示

 記事の一覧表示において、個々の記事にその記事の投稿者のメールアドレスにメールを送信するためのメール用リンクを表示するようにします。

 インクルードファイルcommon_bbs02e.phpファイル内のmessage_disp()関数を以下のように改造します。

common_bbs02e.php

-----(略) -----

// -----------------------------------------------
// 1個の記事本文の表示
function message_disp(&$arr_message)
{
/*
$arr_message['id'] :記事番号
$arr_message['name'] :投稿者氏名
$arr_message['mail'] :投稿者メールアドレス
$arr_message['title'] :記事タイトル
$arr_message['message'] :記事本文
$arr_message['date'] :投稿日時
$arr_message['url'] :関連URL
*/
-----(略) -----
// 「メール」用URL
$str_url_mail = "mailto:" . $arr_message['mail'];
?>
<table class="bd_w1 bd_solid bd_b
         padding3 bd_spacing0 bd_collapse w600">
<tr class="b_dcdcdc xs">
 <td>No.<?=$arr_message['id']?> <?=$arr_message['title']?>
       <span class="fbold">[<?=$arr_message['name']?>] </span>
       <span class="696969"><?=$arr_message['date']?></span></td>
 <td class='ar'><a href="<?=$str_url_mail?>">メール</a>
          <a href="<?=$str_url_response?>">返信</a></td>
</tr>

-----(略) -----

<?php
}

(5)返信記事入力画面でメール送信を選択できるようにする

 返信記事入力画面で、ラジオボタンによりメール送信を選択できるようにします。そのために、インクルードファイルcommon_bbs02e.phpファイル内のresponse_form_disp()関数を以下のように改造します。

common_bbs02e.php

-----(略) -----

// ----------------------------------------------
// 入力フォームの表示
function response_form_disp($status,$parent_id,$str_name,$str_mail_address
                  ,$str_title,$str_message,$str_url,$str_pwd
                  ,$str_parent_mail_address,$mail_send)
{
/*
$parent_id :親記事番号
$str_name :投稿者氏名
$str_mail_address :メールアドレス
$str_title :記事タイトル
$str_message :記事本文
$str_url :関連URL
$str_pwd :パスワード
$str_parent_mail_address :親記事投稿者のメールアドレス
$mail_send :メール送信フラグ("yes":メール送信する"no":しない)

*/

-----(略) -----

<tr>
 <td>&nbsp;</td>
 <td>この記事を次の投稿者にメールでも送信
   <input type="radio" name="mail_send" value="yes">する
   <input type="radio" name="mail_send" value="no">しない<br>
   <?=$str_parent_mail_address?></td>
</tr>
<tr>
 <td> </td><td><input type=submit name="command" value="送信"></td>
</tr>
<input type="hidden" name="parent_id" value="<?=$parent_id?>">
<input type="hidden" name="parent_mail_address"
    value="<?=$str_parent_mail_address?>">

</form>
</table>
<?php
}

(6)メールの送信

 返信記事入力画面でメール送信を「する」がオンの場合、メールを自動送信するようにします。

Windows OSの場合、メールは以下のphp.iniで設定されるメールサーバからメールが送信されます。

c:\WINDOWS\php.ini 内の設定

[mail function]
; For Win32 only.
SMTP = smtp.yc.musashi-tech.ac.jp
smtp_port = 25

; For Win32 only.
sendmail_from = bbs_admin@yc.musashi-tech.ac.jp

 

 response02e.phpで「送信」ボタンがクリックされた場合の処理を以下のように改造します。

response02e.php

-----(略) -----

 // 「送信」の場合
 elseif($_POST['command'] == "送信")
 {
  $status = "after";
  // データの受信
  $parent_id = $_POST['parent_id'];
  $str_parent_mail_address = $_POST['parent_mail_address'];
  $mail_send = $_POST['mail_send'];


  // 受信データのチェック
  $str_error_message = data_check($str_name,$str_mail_address,$str_title
                  ,$str_message,$str_url,$str_pwd);
  if($str_error_message == "")
  {

   -----(略) -----

   // メール送信
   if(MAIL_SEND && $mail_send == "yes")
   {
    mb_language('Japanese');
    $mail_to = $str_parent_mail_address;
    $str_subject = $str_title;
    $mail_from = "From: " . $str_mail_address;
    // メール送信
    mb_send_mail($mail_to,$str_subject,$str_message,$mail_from);
   }

   // データのリセット
   $new_id = "";

   -----(略) -----

 たとえば、返信記事入力画面には以下のようにメール送信選択のラジオボタンが表示されます。

 

 


前へ | 目次へ |次へ  | YCポータルサイト

執筆 山田豊通
更新日: 2006年12月2日