投票ページの作成 (DB編)

はじめに

前回までに、様々な課題を残しつつも動作した投票ページのデータを DB に記録するようにしてみます。


作業概要

システム概要

実装を始める前に、実行環境を Apach, PHP, PostgreSQL と仮定して全体のシステムを確認してみましょう。

まず、PHP は Apache に含まれると考えてもあまり問題ありませんが、PostgreSQL はそれ自体がサービスであり、Apache とは別に考えましょう。

voteSystem.png

Apache と PostgreSQL の関係

このあたりの話は、後ほど実装のあたりで出てきます。

投票用 DB, テーブルの定義

データをファイルに保存する PHP ページでは、保存データはディレクトリ毎で別のファイル名であれば、ユニーク性を保証できました。PostgreSQL で同様のことを実現するには、保存するレコード毎にどのページの投票結果を示す物を持たなければなりません。

以上を踏まえ、tag という名前のフィールドを導入したテーブル定義は以下の通りです。

  CREATE TABLE vote_info (
        tag varchar(20),
        title varchar(80),
        num int,
        PRIMARY KEY (tag, title)
  ); 

実装項目の確認

前回は、voteClass.php というファイルを用いてファイルと PHP とのやりとりを行いましたが、今回は dbVoteClass.php というファイルに処理を実装しましょう。
ここで、voteClass.php で定義した load(), add(), save() と同じメソッド名を用いることにすれば、votePage.php もあまり変更せずにすみます。では、実装開始です。


実装作業

テスト定義

では、テストを実装してしまいます。というか、load(), save() で使うのがファイル名でなくてタグになったのと、初期ファイルと同じ内容を DB に用意しているあたりが異なるだけで、基本的には同じです。

テスト定義

<?php
/*
  dbVoteClass.php 、ホ・ニ・ケ・ネ
  Satofumi KAMIMURA
  $Id
*/

error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
require_once('phpunit/phpunit.php');
require_once('dbVoteClass.php');


class VoteClassTest extends TestCase {
  var $voteObj;

  // ・ウ・ケ・ネ・鬣ッ・ソ
  function VoteClassTest($name) {
    $this->TestCase($name);
  }

  // ・ニ・ケ・ネ、ホス魘ス
  function setUp() {
    $this->voteObj = new DBVoteClass();

    $this->voteObj->voteInfo['、ヲ、オ、ョ、オ、] = 8;
    $this->voteObj->voteInfo['、ュ、熙オ、] = 4;
    $this->voteObj->voteInfo['、ソ、フ、ュ、オ、] = 1;
    $this->voteObj->save('loadSample');

    // タ゜ト熙キ、ソヌロホホニ簣ニ、テオ    array_splice($this->voteObj->voteInfo, 0);
  }

  // ・ニ・ケ・ネ、ホスェホサ
  function tearDown() {}


  // 、ハ、ォ。「コヌス鬢ホ・ニ・ケ・ネ、ャ・ィ・鬘シ、ヒ、ハ、ホ、ヌ・タ・゜。シ・ニ・ケ・ネ、ネ、キ、ニトノイテ
  function testDummy() {
  }
  

  // ニノ、゜スミ、キ・ニ・ケ・ネ
  function testLoad() {
    $this->voteObj->load('loadSample');
    
    $this->assertEquals(8, $this->voteObj->voteInfo['、ヲ、オ、ョ、オ、]);
    $this->assertEquals(4, $this->voteObj->voteInfo['、ュ、熙オ、]);
    $this->assertEquals(1, $this->voteObj->voteInfo['、ソ、フ、ュ、オ、]);
  }
  

  // ナシ・ニ・ケ・ネ
  function testAdd() {
    $this->voteObj->load('loadSample');

    // エ鈐クケ猯ワ、ヒツミ、キ、ニ、ホナシ
    $this->voteObj->add('、ソ、フ、ュ、オ、);
    $this->assertEquals(2, $this->voteObj->voteInfo['、ソ、フ、ュ、オ、]);

    // ソキオャケ猯ワ、ホトノイテ
    $this->voteObj->add('、セ、ヲ、オ、);
    $this->assertEquals(1, $this->voteObj->voteInfo['、セ、ヲ、オ、]);
  }

  
  // スュケ゜・ニ・ケ・ネ
  function testSave() {
    $this->voteObj->load('loadSample');
    $this->voteObj->add('、ソ、フ、ュ、オ、);
    $this->voteObj->add('、セ、ヲ、オ、);
    $this->voteObj->save('saveSample');

    $this->voteObj->load('saveSample');
    $this->assertEquals(8, $this->voteObj->voteInfo['、ヲ、オ、ョ、オ、]);
    $this->assertEquals(4, $this->voteObj->voteInfo['、ュ、熙オ、]);
    $this->assertEquals(2, $this->voteObj->voteInfo['、ソ、フ、ュ、オ、]);
    $this->assertEquals(1, $this->voteObj->voteInfo['、セ、ヲ、オ、]);
  }
}
?>

<html>
<head>
<title>VoteClassTest</title>
<STYLE TYPE="text/css">
<?php
include ("stylesheet.css");
?>
</STYLE>
</head>
<body>
<?php
$suite = new TestSuite('VoteClassTest');
$result = new PrettyTestResult;
$suite->run($result);
$result->report();
?>

で、テストを通過したのがこれ。

<?php
/*
  ナシオ。ヌス、ホエノヘッ・鬣ケ
  Satofumi KAMIMURA
  $Id$
*/


class DBVoteClass {

  var $voteInfo;
  var $tag;
  var $DB_NAME, $DB_HOST, $DB_USER, $DB_PASSWORD;
  var $db;

  
  // ・ウ・ケ・ネ・鬣ッ・ソ
  function DBVoteClass() {
    $this->DB_NAME = 'db_practice';
    $this->DB_HOST = 'localhost';
    $this->DB_USER = 'www';
    $this->DB_PASSWORD = '';

    $this->db = false;
    $this->connect();
  }


  // タワツウ、ヤ、ヲ
  function connect() {
    if ($this->db != false) {
      return;
    }
    $this->db = pg_connect("dbname=$this->DB_NAME host=$this->DB_HOST".
                           " user=$this->DB_USER password=$this->DB_PASSWORD");
  }

  
  // タワツウ、ト、ク、  function close() {
    if ($this->db != false) {
      pg_close($this->db);
      $this->db = false;
    }
  }
  

  // ・ソ・ー、リト熙キ、ニニノ、゜スミ、キ
  function load($tag) {
    $this->connect();
    
    $this->tag = $tag;
    $sql = "SELECT title, num FROM vote_info WHERE tag='$tag';";
    $rec = pg_query($this->db, $sql);
    if (!$rec) {
      return;
    }
    while (($result = pg_fetch_array($rec)) != false) {
      $title = $result['title'];
      $num = $result['num'];
      $this->voteInfo[$title] = (int)$num;
    }
  }


  // サリト猯ワ、ヒ」アノシトノイテ
  function add($title) {
    if (!isset($this->tag)) {
      return;
    }
    if (array_key_exists($title, $this->voteInfo)) {
      $num = ++$this->voteInfo[$title];
      $sql = "UPDATE vote_info SET num=$num WHERE tag='$this->tag' and title='$title';";
    } else {
      $this->voteInfo[$title] = 1;
      $sql = "INSERT INTO vote_info (tag, title, num) VALUES ('$this->tag', '$title', 1);";
    }
    pg_query($this->db, $sql);
  }
  
  
  // ・ソ・ー、リト熙キ、ニハンツク
  function save($tag) {
    $this->connect();

    // ナマ、オ、ソ tag 、ャ。「ニノ、゜ケタ tag 、ネーロ、ハ、遉ヒ、マセ蠖ュハンツク
    if ($tag != $this->tag) {
      $sql = "DELETE FROM vote_info WHERE tag='$tag';";
      pg_query($this->db, $sql);

      foreach ($this->voteInfo as $key => $val) {
        $sql = "INSERT INTO vote_info (tag, title, num) VALUES ('$tag', '$key', $val);";
        pg_query($this->db, $sql);
      }
    }
    $this->close(); // タワツウ、ト、ク、ニ、ェ、ッ
  }
}
?>

最後に、最初のクラス宣言のあたりのみ変更した投票ページがこれ。

<?php
/*
  ナシ・レ。シ・ク
  Satofumi KAMIMURA
  $Id$
*/
require_once('dbVoteClass.php');
$obj = new DBVoteClass();
$obj->load('loadSample');
$this_page = strtok(basename($_SERVER['REQUEST_URI']), '?&#');

// ナシ、オ、ソ、鬘「ツュ、キケヌハンツク、キトセ、ケ
if (isset($_GET['add'])) {
  $obj->add(urldecode($_GET['add']));
  $obj->save('loadSample');
}
?>
<html><head><title>ナシ・レ。シ・ク</title></head>
<body>
ナシキフ<br>
<br>
<?php
// クスコ゜、ホナシキフ、ホニノ、゜スミ、キ
if (count($obj->voteInfo) <= 0) {
  echo 'イ盞釥ホナシセャ、「、熙゛、サ、」';
} else {
  arsort($obj->voteInfo);
  reset ($obj->voteInfo);
  while (list ($key, $val) = each ($obj->voteInfo)) {
    $encoded = urlencode($key);
    echo "$key, $val, <a href=$this_page?add=$encoded>ナシ</a><br>";
  }
}
?>
<br>
ソキオャケ猯ワ、ホトノイテ<br>
<br>
!!! フ、シツチbr>
</php
?>
</body>

がんばった。


まとめ

以上が、DB の場合の投票クラスです。別に PHP に限ったことではないですが、ユーザアプリケーション(この場合 votePage.php) に対してのインターフェース(この場合、load, add, save のこと)を定義するのがよいでしょう。そうすることで、アプリケーションはデータの実処理の変更に強くなります。ま、そんな感じです。

今後は、ここまでの内容を Smarty でやろうかと思ってるんですが、微妙...。


Generated on Mon Apr 13 22:52:06 2009 by  doxygen 1.5.7.1