データベース作成
サンプル作成の最初に、Zend_Dbでアクセスする対象となるデータベースを用意します。MySQLのコマンドラインツールを使って管理者ユーザでログインし、次の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を検索します。
<?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, wolrd!のZend_Db版ができあがりました。
結果を取得するメソッドはfetchAllの他にも、次のようなものがあります。
メソッド名 | 概要 |
fetchCol | 1列目のみを配列で返します。2列目以降は捨てられます。 |
fetchPairs | 1列目をキーに2列目の値を格納した配列で返します。3列目以降は捨てられます。1列目の値が重複した行は上書きされます。 |
fetchRow | 1行目のみを配列で返します。2行目以降は捨てられます。 |
fetchOne | 1行目の1列目のみを返します。 |
実用的な検索
次は、もっと実用的な検索を取り上げます。以下の要素を見ていきます。
- 設定情報を別ファイルへ切り出す
- Zend_Db_Statement_Pdoクラスの利用
- データベースへの接続・切断の制御
hello_world.phpではデータベースに接続するためのユーザ名やパスワードといった設定情報を直にプログラム中に書き込んでいましたが、まずはこれを別のファイルへ切り出します。これで、複数のphpファイルから1つの設定を共有できます。また、設定情報を書いたファイルを外部からアクセスできない場所に置くことでセキュリティを強化できます。
iniファイルに設定情報を書き、Zend FrameworkのZend_Configコンポーネントを使って読み込みます。
[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クラスを使います。
<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クラスのオブジェクトを使うと便利です。
<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オブジェクトが返されます。
SELECT文の句とZend_Db_Selectの主なメソッドの対応を表にまとめます。なお、これらのメソッドはSELECT文の語順と異なる順序で呼び出しても問題ありません。
SELECT文の句 | メソッド |
FROM | from() |
DISTINCT | distinct() |
JOIN | join() |
LEFT OUTER JOIN | joinLeft() |
RIGHT OUTER JOIN | joinRight() |
FULL OUTER JOIN | joinFULL() |
WHERE | where()、orWhere() |
GROUP BY | group() |
HAVING | having() |
ORDER BY | order() |