新規ドキュメントはこちら(http://ozaki.kyoichi.jp/content/blogsection/4/26/)に掲載しております。
DB (pear) のインストール
pearのDBを入手します。現時点(2005/01/21)では1.6.8 リリースとなっています(こちらから入手できます)。 今回はシステムのpearにインストールしますが、ホットデプロイを考えると、必要なpear関連のファイルだけまとめて、プロジェクトディレクトリに含めてしまうのが良いのではないかと思います。これについては、時間を見て追記したいと思います。
[k-ozaki@free15 ~]$ su - [root@free15 ~]# pear install DB
今回のサンプルはPostgreSQLを例にして解説いたします。まずはPostgreSQLのユーザとデータベースの準備をします(あまりmojaviと関係なので簡単に)。いずれもmyprojectという名前で作成します。手儒は以下のようになります
[k-ozaki@free15 ~]$ su - [root@free15 ~]# su - postgres -bash-3.00$ createuser myproject -bash-3.00$ createdb -E UNICODE myproject -bash-3.00$ psql template1 template1=# alter user myproject with password 'myproject';
作成したユーザとデータベースにアクセスできるようにPostgreSQLを設定します。手順は以下のようになります
[root@free15 ~]# vi /var/lib/pgsql/data/pg_hba.conf
host myproject all 127.0.0.1 255.255.255.255 md5 local myproject all md5
ネットワーク上(ウェブサーバ)からPostgreSQLに繋げられるように設定します。ついでに発行するSQL文がsyslogにより、ログに保存されるように設定します(何かとアプリケーションのデバッグに便利です)。手順は以下のようになります
[root@free15 ~]# vi /var/lib/pgsql/data/postgresql.conf
tcpip_socket = true syslog = 2 log_statement = true
[root@free15 ~]# vi /etc/syslog.conf
local0.* /var/log/pgsql
設定を有効にするために、PostgreSQLとsyslogを再起動します
[root@free15 ~]# service postgresql restart
[root@free15 ~]# service syslog restart
Global ConfigurationにPostgreSQLの設定を追記します。MyProject/webapp/config.phpに、以下の定数を追加します
// Database Configuration
define('MY_DB_PHPTYPE', 'pgsql');
define('MY_DB_HOSTSPEC', '127.0.0.1');
define('MY_DB_PORT', '5432');
define('MY_DB_DATABASE', 'myproject');
define('MY_DB_USERNAME', 'myproject');
define('MY_DB_PASSWORD', 'myproject');
次に、DBを使うための汎用クラスを作ります。MyProject/lib/JP/BANCHO/Database/Commonというディレクトリを作成して、MyProject/lib/JP/BANCHO/Database/Common/ConnectionFactory.class.phpを作成します。以下のような内容になります
[k-ozaki@free15 ~]$ mkdir -p ~/workspace/MyProject/lib/JP/BANCHO/Database/Common/
ConnectionFactory.class.php
<?php
require_once(MY_PEAR_DIR . "/DB.php");
class ConnectionFactory {
function getConnection() {
$dsn = array (
'phptype' => MY_DB_PHPTYPE,
'hostspec' => MY_DB_HOSTSPEC,
'port' => MY_DB_PORT,
'database' => MY_DB_DATABASE,
'username' => MY_DB_USERNAME,
'password' => MY_DB_PASSWORD,
);
$options = array (
'debug' => 2,
);
$db =& DB::connect($dsn, $options);
if (DB::isError($db)) {
die($db->getMessage());
}
return $db;
}
}
?>
サンプル用のテーブル(M_USER)の作成とダミーデータをINSERTします
[k-ozaki@free15 ~]$ psql myproject myproject myproject=> create table M_USER (
myproject(> USER_ID VARCHAR(16),
myproject(> LAST_NAME TEXT,
myproject(> FIRST_NAME TEXT,
myproject(> PRIMARY KEY (USER_ID)); myproject=> insert into M_USER values ('ozaki', '尾崎', '恭一');
ここで、サンプル用のアクションで使う汎用クラスを用意します。これらは、通常データベース定義書などから自動生成されるクラスファイルになります。
M_USERを取り扱うValueオブジェクト。MyProject/webapp/lib/JP/BANCHO/Logic/Value/UserValue.class.php
<?php
/**
* ユーザ情報Valueクラス
* @access public
* @package JP/BANCHO/Logic/Value
* @category Value
* @author Kyoichi Ozaki <k@bancho.jp>
* @sourcefile
*/
class UserValue {
/** ユーザID */
private $userId;
/** 氏名(姓) */
private $lastName;
/** 氏名(名) */
private $firstName;
/**
* ユーザIDを取得します。
* @return String
*/
function getUserId() {
return $this->userId;
}
/**
* ユーザIDをセットします。
* @param String
*/
function setUserId($string) {
$this->userId = $string;
}
/**
* 氏名(姓)を取得します。
* @return String
*/
function getLastName() {
return $this->lastName;
}
/**
* 氏名(姓)をセットします。
* @param String
*/
function setLastName($string) {
$this->lastName = $string;
}
/**
* 氏名(名)を取得します。
* @return String
*/
function getFirstName() {
return $this->firstName;
}
/**
* 氏名(名)をセットします。
* @param String
*/
function setFirstName($string) {
$this->firstName = $string;
}
}
?>
データベースを扱うためのDAOクラス。MyProject/webapp/lib/JP/BANCHO/Database/DAO/DatabaseAccessObject.class.php と MyProject/webapp/lib/JP/BANCHO/Database/DAO/UserDAO.class.phpの2クラス。DatabaseAccessObjectが親クラスで、それを継承して、M_USERテーブルのデータを取り扱うようにしているのがUserDAO.class.phpです
<?php
class DataAccessObject
{
protected $db = null;
function __construct($db)
{
$this->db = $db;
}
}
?>
<?php
/*
* ユーザに関わるデータにアクセスするクラス
* @access public
* @package JP/BANCHO/Database/DAO
* @category DAO
* @author Kyoichi Ozaki <k@bancho.jp>
* @sourcefile
*
*/
class UserDAO extends DataAccessObject {
function __construct($db) {
parent::__construct($db);
}
/*
* ユーザIDによりユーザの詳細を返します
* @access public
* @param String ユーザID
* @return Object UserValue
*
*/
function searchUserDetail($userId) {
$sql = " select USER_ID, FIRST_NAME, LAST_NAME ";
$sql.= " from M_USER ";
$sql.= " where USER_ID = '".$userId."' ";
$sth = $this->db->prepare($sql);
$rs =& $this->db->execute($sth);
if (DB::isError($rs)) {
error_log($rs->getMessage());
}
$value = NULL;
if ($row =& $rs->fetchRow()) {
$value = new UserValue();
$value->setUserId($row[0]);
$value->setFirstName($row[1]);
$value->setLastName($row[2]);
}
return $value;
}
}
?>
さらにDAOを操作するためのサービスクラスを2つ。MyProject/webapp/lib/JP/BANCHO/Logic/Service/Service.class.phpとMyProject/webapp/lib/JP/BANCHO/Logic/Service/UserService.class.phpの2ファイル。Service.class.phpがDAOを操作する親クラスで、UserService.class.phpは、M_USERテーブルに関するデータを取り扱うためのクラスです。
<?php
class Service {
protected $db = null;
function __construct() {
$this->db = ConnectionFactory::getConnection();
}
function begin() {
$this->db->autoCommit(false);
$this->db->query("BEGIN");
}
function commit() {
$this->db->query("COMMIT");
$this->db->autoCommit(true);
}
function rollback() {
$this->db->query("ROLLBACK");
$this->db->autoCommit(true);
}
}
?>
<?php
/*
* ユーザに関するサービス
* @access public
* @package JP/BANCHO/Logic/Service/
* @category Service
* @author Kyoichi Ozaki <k@bancho.jp>
* @sourcefile
*
*/
class UserService extends Service {
/*
* コンストラクタ
* @access public
*
*/
function __construct() {
parent::__construct();
}
/*
* ユーザIDコードよりユーザの詳細を返します
* @access public
* @param String ユーザID
* @return Object UserValue
*
*/
function searchUserDetail($userId) {
$dao = new UserDAO($this->db);
$value = $dao->searchUserDetail($userId);
return $value;
}
}
?>
で、おきまりのオートローダーの設定。MyProject/webapp/config/autoload.iniにこれらのクラスの定義を追加します。内容は以下のようになります
ConnectionFactory = "%MO_WEBAPP_DIR%/lib/JP/BANCHO/Database/Common/ConnectionFactory.class.php"
DataAccessObject = "%MO_WEBAPP_DIR%/lib/JP/BANCHO/Database/DAO/DataAccessObject.class.php"
UserDAO = "%MO_WEBAPP_DIR%/lib/JP/BANCHO/Database/DAO/UserDAO.class.php"
UserValue = "%MO_WEBAPP_DIR%/lib/JP/BANCHO/Logic/Value/UserValue.class.php"
Service = "%MO_WEBAPP_DIR%/lib/JP/BANCHO/Logic/Service/Service.class.php"
UserService = "%MO_WEBAPP_DIR%/lib/JP/BANCHO/Logic/Service/UserService.class.php"
これでやっと準備完了!!あとはこれまでに散々作ってきたモジュールの作成方法に従ってActionとViewとtemplateを作成するだけです。どんどんすすめて行きましょう。まずは、アクションから。MyProject/webapp/modules/HelloWorld/action/HelloWorldDBAction.class.php
<?php
class HelloWorldDBAction extends MyAction
{
public function execute ()
{
$service = new UserService();
$value = $service->searchUserDetail('ozaki');
$context =& $this->getContext();
$request =& $context->getRequest();
$request->setAttribute('userValue', $value);
return View::SUCCESS;
}
}
?>
ViewのMyProject/webapp/modules/HelloWorld/views/HelloWorldDBSuccessView.class.php
<?php
class HelloWorldDBSuccessView extends MySmartyQuickFormView
{
public function execute ()
{
$context =& $this->getContext();
$request =& $context->getRequest();
$value =& $request->getAttribute('userValue');
$this->setAttribute('userValue', $value);
$this->setTemplate('HelloWorldDBSuccess.tpl');
}
}
?>
templateのMyProject/webapp/modules/HelloWorld/templates/HelloWorldDBSuccess.tpl
<html>
<body>
Hello World!<br>
This is a Smarty Template with PEAR DB.<br>
<hr>
USER_ID:{$userValue->getUserId()}<br>
LAST_NAME:{$userValue->getLastName()}<br>
FIRST_NAME:{$userValue->getFirstName()}<br>
<hr>
</Body>
</html>
上記手順については作成方法も命名規則もいままで説明してきたとおりの内容なので、特に解説する必要は無いと思います。最後に、ブラウザより、データベースにpsqlコマンドで投入したダミーデータが正しく表示されるか確認します
http://localhost/MyProject/index.php?module=HelloWorld&action=HelloWorldDB
これだけできればたいがいのウェブアプリケーションはmojavi 3で作れると思います。以降の章では複雑な処理系(ウェブアプリケーションでありがちな…)などを作るときのTIPSやHOWTOを紹介していきたいと思います。あぁ疲れた…