掲示板を作成しているのですが困ってます - PHPプロ!Q&A掲示板

2432

  • 1000P

掲示板を作成しているのですが困ってます

質問日時 / 2009年12月30日 19:23    回答数 / 4件

Questioner:  iwskmkt  このエントリーをはてなブックマークに追加 

キーワード / 掲示板 返信    掲示板 削除   

PHP初心者です。

掲示板を作成しており、盛り込みたい機能が3点あるのですが、参考書、サンプルスクリプトをいろいろと見て勉強しているのですがどうしても出来ずに困ってます。


1.投稿された内容に対しコメント(返信)機能を付けたいです。
 PHPプロ!Q&A掲示板のように、投稿内容をクリックすると詳細に飛びコメントできるようにし、レスも表 記されるような形がベストです。

2.投稿した内容を削除キーを使って削除できるようにしたいです。
 投稿した本人であればいつでも削除できるようにいしたいと思ってます。
 記事番号等を選ぶのではなく、コメント横に削除ボタンがあれば良いと思ってます。

3.PHPプロ!Q&A掲示板のトップ画面のように、投稿内容にコメントが追記された場合はコメント数のような 形で表記したいです。

現在出来ているコードは、掲示板トップ画面、認証画面(ログイン・ログアウト)、新規投稿画面です。
全てPHPだけで組みたいと思ってます。
下にコードを表記いたします。

どなたかわかる方がいらっしゃいましたら、ご教授いただけないでしょうか。
よろしくお願いいたします。

①掲示板トップ
  1. <?php
  2. // 掲示板の初期設定
  3. global $logfile;
  4. $logfile = "bbslog.txt"//掲示板のログを記録するファイル
  5.  
  6. // 削除や書き込みごと処理ごとに関数を実行する
  7.  
  8. showLog();
  9.  
  10. // ログの表示
  11.  
  12. function showLog()
  13. {
  14.     global $logfile;
  15.     // HTMLヘッダの表示
  16.     echo "<html><body><h1>コミュニティ掲示板へようこそ</h1><hr>";
  17.     echo "<form action='http://localhost/bbstk.php'><input type='submit' name='toukou' value='新規投稿' /></form>";
  18.     // ログがあれば読み込んで表示
  19.     if (file_exists($logfile)) {
  20.         // ファイルの内容(一行ずつ)を配列変数に読み込む
  21.         $logs = file($logfile);
  22.         $id = array_shift($logs)// データの一行目はID
  23.         
  24.         // ページ送りの処理
  25.         
  26.         $per_page = 5// 1ページに発言をいくつ表示するか
  27.         $page = intval($_GET["page"]);
  28.         if ($page <= 0) { $page = 1}
  29.         $offset = ($page - 1) * $per_page;
  30.         $count = count($logs);
  31.         $logs = array_slice($logs$offset$per_page);
  32.         echo "<p>";
  33.         if ($page > 1) {
  34.             $prev = $page - 1;
  35.             echo "[<a href='?page=$prev'>←前へ</a>]";
  36.         }
  37.         if ($count > ($page * $per_page)) {
  38.             $next = $page + 1;
  39.             echo "[<a href='?page=$next'>次へ→</a>]";
  40.         }
  41.         echo "</p>";
  42.         
  43.         // ログの表示
  44.         
  45.         foreach ($logs as $line) {
  46.             list($id,$name,$title,$main,$date) = split("\t"$line);
  47.       echo ("
  48.         <table cellpadding=\"8\" cellspacing=\"1\" border=\"1\" width=\"600\" align=\"center\">
  49.          <tbody>
  50.           <tr>
  51.            <td valign=\"middle\" align=\"left\">
  52.             ");
  53.             echo "<p>$id:<b>$name</b> $date<br/><hr>\n";
  54.             echo "<p>$title</p><hr>\n";
  55.             echo "<blockquote>$main</blockquote></p>\n";
  56.             echo ("
  57.            </td>
  58.           </tr>
  59.          </tbody>
  60.         </table>
  61.       ");
  62.         }
  63.     }
  64.     // フッタの表示
  65.     echo "</body></html>";
  66. }
  67.  
  68. ?>
②新規投稿画面
  1. <?php
  2. require_once 'rogin.php';
  3. ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  4. <html xmlns="http://www.w3.org/1999/xhtml">
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  7. <title>新規投稿画面</title>
  8. </head>
  9.  
  10. <body>
  11. <div>新規投稿画面</div>
  12. <p>
  13. <?php
  14. echo htmlspecialchars($_SESSION['username']ENT_QUOTES);
  15. ?>さんいらっしゃい!
  16. </p>
  17. <p>ログインした方のみが投稿できます!</p>
  18. <p><a href="http://localhost/rogout.php">ログアウトする</a></p>
  19. <?php
  20. // 掲示板の初期設定
  21. global $logfile;
  22. $logfile = "bbslog.txt"//掲示板のログを記録するファイル
  23.  
  24. // メインプログラム
  25.  
  26. // 削除や書き込みごと処理ごとに関数を実行する
  27. $mode = $_POST["mode"];
  28. if ($mode == "write")  { writeLog();  }
  29. if ($mode == "delete") { deleteLog()}
  30.  
  31. // 発言の書き込み
  32.  
  33. function writeLog()
  34. {
  35.     global $logfile;
  36.     // 不正書き込みのチェック
  37.     if (empty($_POST["name"])||empty($_POST["title"])||empty($_POST["main"])) { return}
  38.     // 既存のデータを読み込む
  39.     if (file_exists($logfile)) {
  40.         $logs = file($logfile);
  41.         $id = intval(array_shift($logs))// 一行目はID
  42.     } else { // 初めての時
  43.         $id = 0;
  44.         $logs = array()// 空の配列
  45.     }
  46.     // 今回の書き込みを配列にセット
  47.     $id++;
  48.     $name = $_POST["name"];
  49.     $title = $_POST["title"];
  50.     $main = $_POST["main"];
  51.     $date = date("Y/m/d H:i");
  52.     // HTML化する
  53.     $name = htmlspecialchars($name);
  54.     $title = htmlspecialchars($title);
  55.     $main = htmlspecialchars($main);
  56.     // 本文にある改行を<br/>に置換しておく
  57.     $main = str_replace("\t""&nbsp;"$main);
  58.     $main = str_replace("\n""<br/>"$main);
  59.     $main = str_replace("\r"""$main);
  60.     $main = preg_replace('#(http?://[a-zA-Z0-9\;\:\&\_\.\?\/\#\%\&\=\-\+\~\@]+)#',
  61.         '<a href="$1">$1</a>'$main);
  62.     $newdata = $id."\t".$name."\t".$title."\t".$main."\t".$date."\n";
  63.     array_unshift($logs$newdata);
  64.     // ファイルへ保存
  65.     array_unshift($logs$id."\n");
  66.     file_put_contents($logfile$logs);
  67. }
  68.  
  69. // 発言の削除
  70.  
  71. function deleteLog()
  72. {
  73.     global $logfile;
  74.     // 不正書き込みのチェック
  75.     if (empty($_POST["id"])) { return}
  76.     // ファイルがなければ何もしない
  77.     if (!file_exists($logfile)) { return}
  78.     // ファイルの読み込み
  79.     $logs = file($logfile);
  80.     $last_id = array_shift($logs)// 一行目を退避
  81.     $newlogs = array();
  82.     foreach ($logs as $line) {
  83.         list($id,$name,$title,$main,$date) = split("\t"$line);
  84.         if ($id != $_POST["id"]) { array_push($newlogs$line)}
  85.     }
  86.     // ファイルへ保存
  87.     array_unshift($newlogs$last_id);
  88.     file_put_contents($logfile$newlogs);
  89. }
  90. ?>
  91.  
  92.  
  93.  
  94. <form method="POST"><!-- 書き込みフォーム -->
  95. お名前:<input type='text' name='name' value="<?php
  96. echo htmlspecialchars($_SESSION['username']ENT_QUOTES);
  97. ?>" size="40" /><br/>
  98. <div>カテゴリ</div>
  99. <input type="radio" name="general" value="general" />一般
  100. <input type="radio" name="design" value="design" />デザイン
  101. <input type="radio" name="prog" value="prog" />プログラミング
  102. <input type="radio" name="plan" value="plan" />企画・マネジメント
  103. <div>題名</div><input type='text' name='title' size='50' /><br/>
  104. <textarea name='main' rows='10' cols='50'></textarea><br/>
  105. <input type='hidden' name='mode' value='write'/>
  106. <input type='submit' value='投稿する'/>
  107. </form>
  108. <form action="http://localhost/bbstop.php">
  109. <input type="submit" name="reset" value="戻る" />
  110. </form>
  111. <form method="POST"><!-- 削除フォーム-->
  112. 削除するID:<input type='text' name='id' size='3'/>
  113. <input type='hidden' name='mode' value='delete'/>
  114. <input type='submit' value='削除'/>
  115. </form>
  116.  
  117.  
  118. </body>
  119. <html>
③認証画面
  1. <?php
  2. session_start();
  3.  
  4. # ユーザー名とパスワードを設定します。複数名分の設定ができます。
  5. $userid[]   = 'admin';   // ユーザーID
  6. $password[] = 'pass1';   // パスワード
  7. $username[] = 'テスト';  // お名前
  8.  
  9. $userid[]   = 'test';
  10. $password[] = 'pass2';
  11. $username[] = 'テスト2';
  12.  
  13. # エラーメッセージの変数を初期化します。
  14. $error = '';
  15.  
  16. # 認証済みかどうかのセッション変数を初期化します。
  17. if (!isset($_SESSION['auth'])) {
  18.   $_SESSION['auth'] = FALSE;
  19. }
  20.  
  21. if (isset($_POST['userid']) && isset($_POST['password'])) {
  22.   foreach ($userid as $key => $value) {
  23.     if ($_POST['userid'] === $userid[$key] &&
  24.         $_POST['password'] === $password[$key]) {
  25.       // セッション固定化攻撃対策☆レシピ248☆
  26.       $oldSid = session_id();
  27.       session_regenerate_id(TRUE);
  28.       if (version_compare(PHP_VERSION'5.1.0''<')) {
  29.  
  30.         $path = session_save_path() != '' ? session_save_path() : '/tmp';
  31.         $oldSessionFile = $path . '/sess_' . $oldSid;
  32.         if (file_exists($oldSessionFile)) {
  33.           unlink($oldSessionFile);
  34.         }
  35.       }
  36.  
  37.       $_SESSION['auth'] = TRUE;
  38.       $_SESSION['username'] = $username[$key];
  39.       break;
  40.     }
  41.   }
  42.   if ($_SESSION['auth'] === FALSE) {
  43.     $error = 
  44.       '<font color="red">ユーザーIDかパスワードに誤りがあります。</font><br />';
  45.   }
  46. }
  47.  
  48. if ($_SESSION['auth'] !== TRUE) {
  49. ?>
  50. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  51. <html>
  52. <head>
  53. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  54. <title>簡単なログインフォームを作成したい</title>
  55. </head>
  56. <body>
  57. <div id="login">
  58.   <h1>認証フォーム</h1>
  59.   <?php echo $error;?>
  60.   <form action="" method="post">
  61.     <dl>
  62.       <dt><label for="userid">ユーザーID:</label></dt>
  63.       <dd><input type="text" name="userid" id="userid" value="" /></dd>
  64.     </dl>
  65.     <dl>
  66.       <dt><label for="password">パスワード:</label></dt>
  67.       <dd><input type="password" name="password" id="password" value="" /></dd>
  68.     </dl>
  69.     <input type="submit" name="submit" value="ログイン" />
  70.   </form>
  71. </div>
  72. </body>
  73. </html>
  74. <?php
  75. //スクリプトを終了し、認証が必要なページが表示されないようにします。
  76. exit();
  77. }
  78. /* ?>終了タグ省略) */
④ログアウト画面
  1. <?php
  2. session_start();
  3. //セッション変数をすべて削除します。
  4. $_SESSION = array();
  5. //セッションを破棄します。
  6. session_destroy();
  7. ?>
  8. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  9. <html>
  10. <head>
  11. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  12. <title>ログアウト</title>
  13. </head>
  14. <body>
  15. <div id="mailbox">
  16.   <p>ログアウトしました。</p>
  17.   <p><a href="bbstop.php">戻る</a></p>
  18. </div>
  19. </body>
  20. </html>

この質問への意見の募集は締め切られ、ポイントは既に配分されました。
意見を投稿することはできますが、ポイントを受け取ることはできません。



ツリー一覧

┗A01magicflute2取っ掛かりは、データ構造を見直す所から。 ・IDを
 ┗A01-1iwskmktmagicflute2さん さっそくのアドバイスありがとう
  ┗A01-1-1magicflute2>>CODE <?php /** * serial * マイクロ秒からハ
   ┗A01-1-1-1iwskmktmagicflute2さん ありがとうございます。 発番

回答一覧

並び替え:

A01 参考になった
answerermagicflute2 [12月30日 23:10] (最終編集:12月30日 23:29)

取っ掛かりは、データ構造を見直す所から。

・IDを固定幅の英数で振り、一意な値を発番する関数を作る
 (親IDが連番だと、追加・削除した時に、子との繋がりに整合性が取れなくなる)

・子ID、親削除キー、子削除キーといったプロパティの追加
 (日付が必要なら、20091231 20100101の様にソートしやすくする)

・投稿者が(親)、返信者が(子)の関係となるようにデータ構造を変更する。
 (親と子を一行につなげる、別々のファイルにする、XMLにする、JSONにする等々)

・コメント数 = その親IDに紐づく子IDの数
 (これを踏まえて勘定しやすい形に)

次段階はデータの取得と格納

この意見に回答する

ツリーへ TOPへ

A01-1
replyeriwskmkt [12月31日 08:34]

magicflute2さん

さっそくのアドバイスありがとうございます。

おっしゃる通り、確かに親IDが連番ですと削除したときに整合性が取れなくなりますね。。
一意な値を発番する関数を作りたいと思いますが、どのような関数が必要なのでしょうか?
初心者でどうすればよいかよくわからないのが実情です。

子ID、親削除キー、子削除キーといったプロパティの追加ですね。
わかりました。やってみたいと思います。


>・投稿者が(親)、返信者が(子)の関係となるようにデータ構造を変更する。
>(親と子を一行につなげる、別々のファイルにする、XMLにする、JSONにする等々)
>・コメント数 = その親IDに紐づく子IDの数
>(これを踏まえて勘定しやすい形に)
上記アドバイスを踏まえて、やってみたいと思います。

いろいろわからないことが多いですが、試行錯誤してチャレンジしてみます。

この意見に回答する

ツリーへ TOPへ

A01-1-1 参考になった
replyermagicflute2 [12月31日 14:40]

  1. <?php
  2. /**
  3.  * serial
  4.  * マイクロ秒からハッシュ値を取得し、英大文字列に変換
  5.  * 32桁固定の英数文字列を出力
  6.  * (検索ワード:ハッシュ値 md5)
  7.  */
  8. function serial()
  9. {
  10.   return strtoupper(md5(microtime(true)));
  11. }

あくまでも一例。
試行錯誤した後にでも試してください。
  1. <?php
  2. // XML形式の例
  3. // <![CDATA[]]>セクションの中身はエスケープした方が良い
  4. $bbsdata = <<<XML
  5. <root>
  6.   <datalist>
  7.     <topic id="XXX1" delkey="zzz" title="あいうえお">
  8.       <description><![CDATA[あいうえおあいうえお]]></description>
  9.       <res id="YYY1" delkey="" title="">
  10.         <comment><![CDATA[aiueo]]></comment>
  11.       </res>
  12.       <res id="YYY2" delkey="" title="">
  13.         <comment><![CDATA[aeiou]]></comment>
  14.       </res>
  15.     </topic>
  16.     <topic id="XXX2" delkey="xxx" title="かきくけこ">
  17.       <description><![CDATA[かきくけこかきくけこ]]></description>
  18.       <res id="ZZZ1" delkey="" title="">
  19.         <comment><![CDATA[kakikukeko]]></comment>
  20.       </res>
  21.     </topic>
  22.   </datalist>
  23. </root>
  24. XML;
  25.  
  26. // XMLオブジェクト操作
  27. $obj = simplexml_load_string($bbsdata)// ※注:マニュアルを参照すべし
  28. var_dump($obj);
  29. echo $obj->datalist->topic[0]['id'];
  30. echo $obj->datalist->topic[0]->description;
  31. echo $obj->datalist->topic[0]->res[0]['id'];
  32. echo $obj->datalist->topic[0]->res[0]->comment;

この意見に回答する

ツリーへ TOPへ

A01-1-1-1
replyeriwskmkt [12月31日 17:39]

magicflute2さん

ありがとうございます。

発番する関数ありがとうございます。
すごく勉強になります。
データの取得と格納にXMLを使うのはよさそうですね。
大みそかにもかかわらず、私に付き合って、いろいろアドバイスをいただき本当に感謝しております。

お忙しいとは思いますが、随時アドバイスをいただければ幸いです。
厚かましいのは重々承知しておりますが、何卒よろしくお願いいたします。

この意見に回答する

ツリーへ TOPへ

<<質問一覧へ



Pick Up Q&A

Q
負荷時のmysql_connect()エラー
 このエントリーをはてなブックマークに追加 
A
これはPHPというよりOSまたはMySQLのコミュニティで質問されたほうがいいと思います。 ぱっと思いついた範囲で記すと MySQL等のDBに「ある時点において同時に接続可能なクライアントの最大数」に制限があるよう...

>>続きを読む

今回のような実践的な経験がエンジニアのキャリアに繋がると思います。是非サービスを成功させて下さい!

▲解説者:岡本(アシアル株式会社 教育コーディネーター兼 システムエンジニア)