CodeZine(コードジン)

特集ページ一覧

Zend Framework入門(6):抽象化レイヤによるデータベースアクセス手法 - Zend_Db(前編) -

Zend Frameworkによる実践的なPHPアプリケーション開発 6

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2008/05/15 14:00
目次

データベース作成

 サンプル作成の最初に、Zend_Dbでアクセスする対象となるデータベースを用意します。MySQLのコマンドラインツールを使って管理者ユーザでログインし、次のSQLを実行します。

make_database.sql
-- データベースdb_zend_sampleを作成します
CREATE DATABASE db_zend_sample;

-- ユーザzendを作成し、データベースdb_zend_sampleに対する
-- 全権限を付与します
GRANT ALL ON db_zend_sample.*
TO zend@localhost IDENTIFIED BY 'zend_pass';

-- 使用するデータベースをdb_zend_sampleに切り替えます
use db_zend_sample;

-- テーブルを作成します
CREATE TABLE message_board(
  id int primary key,
  message varchar(100)
) engine = InnoDB;

-- テーブルにレコードを追加します
INSERT INTO message_board VALUES(1, 'Hello, world!');
INSERT INTO message_board VALUES(2, 'How are you?');

 これで、データベース「db_zend_sample」の中にテーブル「message_board」が作られました。列が「id」と「message」の2個だけのシンプルなテーブルですが、「engine = InnoDB」というオプションをつけて作成しました。MySQLのテーブルのデフォルトでは利用できないトランザクションの機能が、このオプションにより他の多くのRDBMSと同じように使えるようになります。テーブルには2行のレコードを入れました。

 データベースにアクセスするためのユーザ「zend」もあわせて作成しました。サンプルプログラムからデータベースにアクセスするときにはzendユーザを利用します。

Zend_Dbでテーブル検索

 それではさっそく、データベースにアクセスしてみましょう。テーブルmessage_boardを3通りの方法で検索します。

シンプルな検索でHello, world!

 まずはシンプルな使い方を見てみましょう。Zend_DbのMySQL用アダプタを利用してテーブルmessage_boardを検索します。

hello_world.php
<?php
// MySQL用アダプタのモジュールを呼び出します
require_once 'Zend/Db/Adapter/Pdo/Mysql.php';

// データベース接続に必要な情報を配列に格納します
$db_info = array('host'     => 'localhost',
                 'username' => 'zend',
                 'password' => 'zend_pass',
                 'dbname'   => 'db_zend_sample');
// MySQL用アダプタのオブジェクトを作ります
$db = new Zend_Db_Adapter_Pdo_Mysql($db_info);

// SELECT文の文字列を作ります
$sql = "SELECT message FROM message_board";
// SELECT文を実行します
$result = $db->fetchAll($sql);
// 配列で返される結果を表示します
foreach ($result as $row) {
    echo $row['message'] . '<br/>';
}

 MySQL用アダプタのオブジェクトを作り、fetchAllメソッドでSELECT文を実行しました。fetchAllメソッドの結果は二次元配列で返されます。変数$rowが1レコードに対応し、列名をキーにして列の値が入っています。

Hello, world!の結果
Hello, world!の結果

 Hello, wolrd!のZend_Db版ができあがりました。

 結果を取得するメソッドはfetchAllの他にも、次のようなものがあります。

結果取得メソッド
メソッド名概要
fetchCol1列目のみを配列で返します。2列目以降は捨てられます。
fetchPairs1列目をキーに2列目の値を格納した配列で返します。3列目以降は捨てられます。1列目の値が重複した行は上書きされます。
fetchRow1行目のみを配列で返します。2行目以降は捨てられます。
fetchOne1行目の1列目のみを返します。

実用的な検索

 次は、もっと実用的な検索を取り上げます。以下の要素を見ていきます。

  • 設定情報を別ファイルへ切り出す
  • Zend_Db_Statement_Pdoクラスの利用
  • データベースへの接続・切断の制御

 hello_world.phpではデータベースに接続するためのユーザ名やパスワードといった設定情報を直にプログラム中に書き込んでいましたが、まずはこれを別のファイルへ切り出します。これで、複数のphpファイルから1つの設定を共有できます。また、設定情報を書いたファイルを外部からアクセスできない場所に置くことでセキュリティを強化できます。

 iniファイルに設定情報を書き、Zend FrameworkのZend_Configコンポーネントを使って読み込みます。

config/db_info.ini
[sample_db]
db.adapter         = Pdo_Mysql
db.params.host     = localhost
db.params.username = zend
db.params.password = zend_pass
db.params.dbname   = db_zend_sample

 configフォルダを作り、その中に設定ファイルを入れることにしました。次はプログラム本体です。SQL文とその結果を保持するZend_Db_Statement_Pdoクラスを使います。

basic_select.php
<html>
<head>
<title>SELECTの例</title>
</head>
<body>
<?php
require_once 'Zend/Db.php';
// Zend_Configのモジュールを読み込みます
require_once 'Zend/Config/Ini.php';

// 設定情報を読み込みます
$config = new Zend_Config_Ini('config/db_info.ini', 'sample_db');
// factoryメソッドでアダプタオブジェクトを作ります
$db = Zend_Db::factory($config->db);

// データベースに接続します
$db->getConnection();

$sql = "SELECT * FROM message_board";
// Zend_Db_Statement_Pdoオブジェクトを取得します
$statement = $db->query($sql);
// 結果を取得して表示します
while($row = $statement->fetch()) {
    echo $row['id'] . ':' . $row['message'] . '<br/>';
}

// データベースから切断します
$db->closeConnection();
?>
</body>
</html>

 利用するアダプタがMySQL用のものであることを設定ファイルに書きました。そのため、Zend_Db_Adapter_Pdo_Mysqlクラスのコンストラクタ呼び出しなど、DBMSの種類に依存したコードを書かなくてよくなりました。これにより、DBMSを変更することがあっても対応が簡単になります。

 アダプタオブジェクトを作った直後、hello_world.phpには無かったgetConnectionメソッドを呼び出しています。このメソッドはデータベースへの接続を行います。getConnectionメソッドを呼ばなかった場合は最初にクエリを実行するときに自動的にデータベースへ接続します。closeConnectionメソッドを呼ばなかった場合は自動的に切断されます。これらのメソッドは、データベースへの接続と切断のタイミングを制御するために使います。

 データベースに自動的に接続していると、複雑なプログラムではデータベース接続の失敗がどこで発生するか分かりづらく、エラー処理が行いにくくなります。このような場合はどこでデータベースに接続するかを決めてgetConnectionメソッドを使うとよいでしょう。

 closeConnectionメソッドは1つのデータベースにアクセスする処理を同時に複数行う必要がある場合など、リソース解放をなるべく早く行いたいときに利用します。

 queryメソッドはZend_Db_Statement_Pdoオブジェクトを返します。オブジェクトには検索結果が保持されており、fetchメソッドを呼ぶことで1行ずつ取り出すことができます。

検索結果の表示
検索結果の表示

Zend_Db_Selectオブジェクトを使った検索

 プログラム中の条件分岐にあわせて実行するSELECT文を変えたい場合、例えば「参照するテーブルを使い分ける」「ORDER BY句によるソートの有無を切り替える」ということがあります。このようなときはZend_Db_Statement_Pdoクラスの代わりにZend_Db_Selectクラスのオブジェクトを使うと便利です。

select_object.php
<html>
<head>
<title>Zend_Db_Selectの使用例</title>
</head>
<body>
<?php
require_once 'Zend/Db.php';
require_once 'Zend/Config/Ini.php';

$config = new Zend_Config_Ini('config/db_info.ini', 'sample_db');
$db = Zend_Db::factory($config->db);

// Zend_Db_Selectオブジェクトを作ります
$select = $db->select();

// SELECT文を組み立てます
$select->from('message_board', 'message');  // message FROM message_board
$select->where('id >= 1');                  // WHERE id >= 1
$select->order('id desc');                  // ORDER BY id desc

// SELECT文を実行します
$statement = $select->query();
while($row = $statement->fetch()) {
    echo $row['message'] . '<br/>';
}

?>
</body>
</html>

 アダプタオブジェクトのselectメソッドを呼ぶと、Zend_Db_Selectオブジェクトが返されます。Zend_Db_Selectオブジェクトのメソッドを呼び出してSELECT文の句を追加していきます。SELECT文が完成したらqueryメソッドを呼び出せば、SELECTの結果を保持したZend_Db_Statement_Pdoオブジェクトが返されます。

Zend_Db_Selectを使った検索の結果
Zend_Db_Selectを使った検索の結果

 SELECT文の句とZend_Db_Selectの主なメソッドの対応を表にまとめます。なお、これらのメソッドはSELECT文の語順と異なる順序で呼び出しても問題ありません。

SELECT文の句とメソッドの対応
SELECT文の句メソッド
FROMfrom()
DISTINCTdistinct()
JOINjoin()
LEFT OUTER JOINjoinLeft()
RIGHT OUTER JOINjoinRight()
FULL OUTER JOINjoinFULL()
WHEREwhere()、orWhere()
GROUP BYgroup()
HAVINGhaving()
ORDER BYorder()

  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:Zend Framework入門

もっと読む

著者プロフィール

  • WINGSプロジェクト 川北 季(カワキタ ミノル)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5