&pgid();
 
 11月から新しく入社した小沼です。現在研修中でPHPの勉強をしています。
 先日、研修の一環として「SmartyとPearDBを利用した掲示板」を作成しました。
 自分の頭の中を整理する意味もこめて、ここにその成果の一部を発表したいと思います。
 
 
 **目次 [#nce29998]
 #contents();
 **概要 [#ffc248be]
 ***環境 [#sf8649dd]
 動作環境 : Linux
 Webサーバ : Apache
 開発言語 : PHP
 DB : MySQL
 使用したライブラリなど : Smarty、PearDB
 開発はWindowsマシンからSSHでLinuxにつなぎ、おこないました。
 ***システム構成 [#z45c15bc]
 作成したアプリケーションは以下のような構成になりました。
 
 smarty_board
 ├ js
 │ └ smarty_board.js     --list.tpl内で利用するjavaScript
 ├ templates
 │ └ list.tpl            --画面のテンプレート
 ├ article_dao.php        --データアクセスオブジェクト
 ├ list.php               --list.tplに変数を設定するモジュール
 ├ paging_manager.php     --ページング管理をおこなうクラス
 └ submit_new_article.php --新規投稿を行うクラス
 
 **困った点 [#k07e5025]
 
 ***Smartyとjavascript [#j6accfa2]
 テンプレートファイルの中では中括弧{}が予約語として扱われます。そのためテンプレート内に以下のような記述をするとエラーになってしまいます。
  function addPageNum(num) {
      document.list_form.page_num.value 
        = new Number(document.list_form.page_num.value) + num;
  }
 回避方法としては以下の二つがあります。
 -javascriptは外部ファイルに記述する。
 -Smartyの中括弧が持っている機能を他の記号に割り当てる。(以下例)
  $smarty->left_delimiter = '<!--{';
  $smarty->right_delimiter = '}-->';
 ちなみに私は前者の方法を取りました。
 
 ***文字化け [#t08c9daa]
 始めはHTMLのエスケープを、Smartyの機能を使いテンプレートの中で以下のようにやろうと思いました。
  <td>{$article.name|escape:"htmlall"}</td>
 そしたら文字化けするようになってしまったので、テンプレートを次のように修正し、
  <td>{$article.name}</td>
 php内で以下の関数を使ってエスケープすることにしました。
  function escape($str) {
      return nl2br(htmlentities($str, ENT_QUOTES, 'EUC-JP'));
  }
 
 ***\nと'(シングルクォーテーション) [#u091fe98]
 入力された値をそのままDBに登録するといろいろ問題が発生します。例えば「\n」が入力されると、改行されて表示されてしまいます。もっとひどいのは「'(シングルクォーテーション)」を入力された場合です。SQLインジェクションが可能になってしまいます。さいわいPHPには
  addslashes()
 という便利な関数があるので、簡単に対応できます。
 
 **ソース [#g1df0ee8]
 ***list.tpl [#g3a926a4]
  <html>
  <head>
  <meta http-equiv="content-type" content="text/html;charset=EUC-JP ">
  <title>スマーティーを利用した掲示板</title>
  
  <script language="javascript" src= "./js/smarty_board.js" ></script>
  
  </head>
  
  <body>
  
  <center>スマーティーを利用した掲示板</center>
  
  <!-- 入力部分 -->
  <form action="submit_new_article.php" name="submit_form" method="POST" >
  <table align="center">
  	<tr>
  		<td>名前</td>
  		<td><input type="text" name="name" size="40"></td>
  	</tr>
  	<tr>
  		<td>内容</td>
  		<td><textarea name="message" rows="6" cols="70" ></textarea></td>
  	</tr>
  	<tr>
  		<td><input type="submit" value="新規投稿" /></td>
  	</tr>
  </table>
  
  </form>
  
  <!-- 一覧部分 -->
  <form action="list.php" name="list_form" method="POST" >
  <input type="submit" value="前へ" {$is_prev_disabled} onclick="addPageNum(-1);" />
  <input type="submit" value="次へ" {$is_next_disabled} onclick="addPageNum(1);" />
  {$page_num} / {$page_count}
  <input type="hidden" name="page_num" value="{$page_num}" />
  
  {foreach from=$articles item=article}
  
  <hr>
  <table>
  	<tr>
  		<td>名前:</td>
  		<!--<td>{$article.name|escape:"htmlall"}</td>-->
  		<td>{$article.name}</td>
  	</tr>
  	<tr>
          <td nowrap>投稿日時:</td>
          <td>{$article.date|date_format:"%Y/%m/%d %H:%M:%S"}</td>
  	</tr>
  	<tr>
  		<td>内容:</td>
  		<td>{$article.message}</td>
  	</tr>
  </table>
  
  {/foreach}
  <hr>
  
  <input type="submit" value="前へ" {$is_prev_disabled} onclick="addPageNum(-1);" />
  <input type="submit" value="次へ" {$is_next_disabled} onclick="addPageNum(1);" />
  {$page_num} / {$page_count}
  
  </form>
  </body>
  </html>
 
 ***list.php [#c12499f7]
  <?php
  
  require_once('Smarty.class.php');
  require('paging_manager.php');
  
  //検索
  $pager = new PagingManager(getPageNum());
  $result = $pager->getArticles();
  
  //画面用のリストに詰め替える。
  $articles = array();
  foreach ($result as $row){
      $articles[sizeof($articles)] 
  	  = array(name=>escape($row[1]), date=>$row[2], message=>escape($row[3]) );
  }
  
  //スマーティーの設定
  $smarty = new Smarty;
  $smarty->assign('articles', $articles);
  $smarty->assign('page_num', getPageNum());
  $smarty->assign('page_count', $pager->getPageCount());
  if (!$pager->hasPrevPage() ) {
      $smarty->assign('is_prev_disabled', 'disabled');
  }
  if (!$pager->hasNextPage()) {
      $smarty->assign('is_next_disabled', 'disabled');
  }
  
  $smarty->template_dir = './templates/';
  $smarty->display('list.tpl');
  
  function getPageNum(){
  
      $page_num = (int) $_POST[page_num];
  	if ($page_num <= 1){
  		$page_num = 1;
  	}
  	return $page_num;
  }
  
  function escape($str) {
      return nl2br(htmlentities($str, ENT_QUOTES, 'EUC-JP'));
  }
  
  ?>
 
 ***submit_new_article.php [#r21ca826]
  <?php
  
  require('article_dao.php');
  
  //画面からの情報を取得する。
  $article = array();
  $article[name] = addslashes($_POST[name]);
  $article[message] = addslashes($_POST[message]);
  
  //DBへの登録処理をおこなう。
  $dao = New ArticleDao;
  $dao -> registArticle($article);
  
  //リダイレクト
  header("Location: http://carrot.ark-web.jp/~konuma/smarty_board/list.php");
  
  ?>
 ***paging_manager.php [#a7afbe30]
  <?php
  
  require('article_dao.php');
  
  define('PAGE_COUNT', 5);
  
  class PagingManager {
  
      var $current_page_num;
  	var $articles;
  	
  	function PagingManager($page_num) {
  		$this->current_page_num = $page_num;
  		
  		$dao = new ArticleDao;
  		$this->articles = $dao->getArticles();
  	}
  
  	function getArticles() {
  	    
          $limit_from = (PAGE_COUNT * $this->current_page_num) - PAGE_COUNT;
  		$limit_to = $limit_from + PAGE_COUNT -1;
  		$index = 0;
          $part_of_articles = array();
  		
  		while($row =& $this->articles->fetchRow()){
              if( $limit_from <= $index && $index <= $limit_to ) {
  				$part_of_articles[sizeof($part_of_articles)] = $row;
  			}
  			$index++;
  		}
  		return $part_of_articles;
  	}
  
  	function hasPrevPage() {
  	    return  ( $this->current_page_num > 1 ); 
  	}
  
  	function hasNextPage() {
          return ( $this->current_page_num * PAGE_COUNT < $this->articles->numRows() );
  	}
  
  	function getPageCount() {
          return ceil($this->articles->numRows() / PAGE_COUNT);
  	}
  
  }
  
  ?>
 
 ***article_dao.php [#nf2ddffb]
  <?php
  
  require('DB.php');
  
  class ArticleDao {
  
  	//一件の投稿をDBに登録する。
  	function registArticle($article) {
  		//コネクション
          $dsn = "mysql://root:@localhost/konuma_training";
  		$db = DB :: connect($dsn, true);
  		
  		//sql文の作成
          $sql = "insert into articles(
                     submitter_name
                    ,submit_date
                    ,message
                  ) values (
                     '$article[name]'
                    ,sysdate()
                    ,'$article[message]'
                  )";
  				
  		//SQLの実行
          $db->query($sql);        
  
          //コネクションの開放
  		$db -> disconnect();
  
  	}
  
  	//DBより書き込みを取得する。
  	function getArticlesLimit($limit_from, $count){
  		
  		//コネクション
          $dsn = "mysql://root:@localhost/konuma_training";
  		$db = DB :: connect($dsn, true);
  		
  		//sql文の作成
          $sql = "select * from articles order by id desc";
  				
  		//SQLの実行
          $result = $db->limitQuery($sql, $limit_from, $count);        
  
          //コネクションの開放
  		$db -> disconnect();
  
          return $result;
  	}
  
  	//DBより書き込みを取得する。
  	function getArticles(){
  		
  		//コネクション
          $dsn = "mysql://root:@localhost/konuma_training";
  		$db = DB :: connect($dsn, true);
  		
  		//sql文の作成
          $sql = "select * from articles order by id desc";
  				
  		//SQLの実行
          $result = $db->query($sql);        
  
          //コネクションの開放
  		$db -> disconnect();
  
          return $result;
  	}
  }
  
  ?>
 
 ***smarty_board.js [#vd9922dc]
  function addPageNum(num) {
  	document.list_form.page_num.value = new Number(document.list_form.page_num.value) + num;
  }
 

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS

アークウェブのサービスやソリューションはこちら