掲示板

概要

今度は掲示板を作ってみます。

データの保存にはデータベースを利用し、
"bbs"というテーブルで掲示板データを格納します。

機能としては、投稿、返信、削除が出来る程度の低機能なものです。

モデルクラス

sample/models/Bbs.php
<?php

class Bbs extends ModelBase
{
    // 記事データを親記事とレス記事の階層状態で取得
    public function getThreads($limit)
    {
        $parents = $this->getParents($limit);
        foreach ($parents as $key => $parent) {
            $res = $this->getResponses($parent['no']);
            $parents[$key]['res'] = $res;
        }
        return $parents;
    }
    
    // 指定件数の親記事を取得
    public function getParents($limit)
    {
        $sql = sprintf("
            SELECT
                *
            FROM
                %s
            WHERE
                parent_no = 0
            ORDER BY
                datetime DESC
            LIMIT
                %s
            ",
            $this->name,
            $limit
        );
        $rows = $this->query($sql);
        
        return $rows;
    }
    
    // 指定の親記事に対するレスを全て取得
    public function getResponses($parentNo)
    {
        $sql = sprintf("
            SELECT
                *
            FROM
                %s
            WHERE
                parent_no = :parent_no
            ORDER BY
                datetime ASC
            ",
            $this->name
        );
        $params = array('parent_no' => $parentNo);
        $rows = $this->query($sql, $params);
        
        return $rows;
    }

    // 記事登録
    public function regist($data)
    {
        $vals['parent_no'] = $data['parent_no'];
        $vals['datetime']  = date('YmdHis');
        $vals['name']  = $data['name'];
        $vals['pass'] = $data['pass'];
        $vals['title'] = $data['title'];
        $vals['contents'] = $data['contents'];
        $res = $this->insert($vals);
        
        return $res;
    }
    
    // 記事削除
    public function del($no)
    {
    	// 指定NOの記事と、そのレス記事を全て削除
        $where = "no = :no OR parent_no = :no";
        $params = array("no" => $no);
        $res = $this->delete($where, $params);
        
        return $res;
    }
}

?>

「モデルの作りこみ」のところで盛り込んだ、便利メソッドをフルに活用しています。

コントローラー

デフォルトアクション(index)は、記事の閲覧ページとします。
今回はインターフェイスとしてはこの一枚だけです。

後のアクションはインターフェイスの存在しない、処理実行用のアクションです。

resアクションは、通常新規投稿用である投稿フォームを、返信フォームモードに切り替えるためのアクションです。記事の返信ボタンをクリックすることで実行されるアクションです。

registアクションは投稿処理の実行。
投稿フォームで「書き込む」をクリックすることで実行されます。
投稿処理完了後はindexアクションへリダイレクトして記事表示を行っています。

deleteアクションは記事の削除です。
記事の削除ボタンをクリックすることで削除を実行します。
これも処理完了後はindexアクションへリダイレクトして記事表示を行っています。

sample/controllers/BbsController.php
<?php

class BbsController extends ControllerBase
{
    // 記事表示
    public function indexAction()
    {
        // データ取得
        $bbs = new Bbs();
        $threads = $bbs->getThreads(100);
        // テンプレートへ出力
        $this->view->assign('threads', $threads);
    }
    
    // 返信モードへ以降
    public function resAction()
    {
        $post = $this->request->getPost();
        
        $this->view->assign('parent_no', $post["parent_no"]);
        $this->indexAction();
        $this->templatePath = 'bbs/index.tpl';
    }
    
    // 投稿処理
    public function registAction()
    {
        $post = $this->request->getPost();
        
        $bbs = new Bbs();
        $bbs->regist($post);
        
        $this->redirect('/bbs/index');
    }
    
    // 削除処理
    public function deleteAction()
    {
        $post = $this->request->getPost();
        
        $bbs = new Bbs();
        $bbs->del($post['no']);
        
        $this->redirect('/bbs/index');
    }
}

?>

ビューテンプレート

テンプレートです。

sample/views/bbs/index.tpl
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 
Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
{literal}
div.messages {
  width:800px;
}
div.parent {
  border:1px solid #888888;
  margin:20px 0 0 0;
  padding:10px;
}
div.parent div.message {
  margin:10px 10px 10px 30px;
}
div.child {
  border-top:1px solid #888888;
  margin:10px 10px 0 30px;
  padding:10px;
}
div.child div.message {
  margin:10px 10px 10px 30px;
}
span.message {
  color:#FF0000;
}
form {
  display:inline;
  margin:0;
  padding:0;
}
{/literal}
</style>
</head>
<body>

<form method="post" action="/sample/system/htdocs/bbs/regist">
  名前<br /><input type="text" name="name" size="50" /><br />
  タイトル<br /><input type="text" name="title" size="50" /><br />
  本文<br /><textarea name="contents" cols="50" rows="8"></textarea><br />
  <input type="hidden" name="parent_no" value="{$parent_no}" />
  <input type="submit" name="write" value="書き込む" />
  {if $parent_no != ""}
  <span class="message">No.{$parent_no}への返信です</span>
  {/if}
</form>

<div class="messages">

{foreach from=$threads item=parent}
  <div class="parent">
    <div class="header">
      No.{$parent.no} {$parent.title} 投稿者名:{$parent.name}
      <form method="post" action="/sample/system/htdocs/bbs/res">
        <input type="hidden" name="parent_no" value="{$parent.no}" />
        <input type="submit" name="res" value="返信" />
      </form>
      <form method="post" action="/sample/system/htdocs/bbs/delete">
        <input type="hidden" name="no" value="{$parent.no}" />
        <input type="submit" name="del" value="削除" />
      </form>
    </div>
    <div class="message">{$parent.contents}</div>
    {foreach from=$parent.res item=res}
    <div class="child">
      <div class="header">
        {$res.title}  {$res.name}
        <form method="post" action="/sample/system/htdocs/bbs/delete">
          <input type="hidden" name="no" value="{$res.no}" />
          <input type="submit" name="del" value="削除" />
        </form>
      </div>
      <div class="message">{$res.contents}</div>
    </div>
    {/foreach}
  </div>
{/foreach}

</div>

</body>
</html>