PHPで利用可能なORMライブラリと特徴
ORMは、Javaや.NETなどの言語ごとにさまざまなプロジェクトが存在しています。PHPでは以下に挙げる4つのプロジェクトがメジャーです。
- Doctrine
- Propel
- php activerecord
- PHPDAO
ORMの特徴を知るため、まず抽象度と機能をグラフにマッピングしてみました。抽象度が高ければ高いほどデータの操作をオブジェクト指向で行うことができます。その結果として、SQLを書く機会が少なくなります。また、機能が多ければ多いほどレコードキャッシュ、スキーマのマイグレーションなどのサポートツールが多くなり、運用を行いやすくなります。
PHPで利用できるORMの抽象度と機能を把握するため、以下にマッピングを作成しました。機能比較のためにPHP自体で提供しているmysql_query()などのMySQL関数とPDO(PHP Data Object)も記載しています。
次に、各ORMのオートコンプリートのサポート有無、対応するPHPのバージョン、ライセンスを記載します。
Doctrine | Propel | php-activerecord | PHPDAO | |
オートコンプリート | ○ | ○ | × | ○ |
対応バージョン | "PHP5.2+(1.2) PHP 5.3+(2.0)" |
PHP5+ | PHP5.3+ | PHP5+ |
ライセンス | LGPL 2.1 | LGPL3+ | MIT | - |
ORMによっては、ORM用のクラスは生成せず、オートコンプリートが使えない場合があるので注意してください。最近のORMの動向としてはPHP5.3以上しかサポートしないライブラリが増えてきたため、利用する場合はPHP5.3でのコーディングをお勧めします。
サンプルコードの実行環境
ORMを利用するためのコードはORMによって特徴が異なるので、各ORMでどのようなコードを記述するかを紹介します。サンプルコードは、ormというデータベースにauthorという名前のテーブルがある前提で解説します。テーブルにはID、ユーザー名とパスワードを保存するカラムがあります。以下に、外部スキーマの図とテーブルを構築するためのMySQL用のSQL文を記載します。
以下に、上記の外部スキーマを構築するためのSQLを記載します。
CREATE TABLE `author` ( `id` INT NOT NULL AUTO_INCREMENT , `name` VARCHAR(255) NOT NULL , `password` CHAR(42) NOT NULL , PRIMARY KEY (`id`) ) ENGINE = InnoDB;
本記事で掲載するサンプルコードではこのテーブルに対して、CRUD(追加、読み取り、更新、削除)を行うコードを記述します。
サンプルコードは上部リンクよりダウンロードできます。サンプルコード内で利用しているデータベースのホストは192.168.0.40、ユーザー名はdbdesignerとなっているので、適宜変更をお願いします。
Doctrine
DoctrineはsymfonyというWebアプリケーションフレームで利用されている有名なORMです。DoctrineはDBALとORMという2つのプロジェクトから構成されています。DBALはPDOのラッパーとして動作し、データベースへの基本的な問い合わせであるCRUD操作を提供します。ORMの方はJavaのHibernateを参考に設計されており、アプリケーションからはDoctrine独自のDQLという問い合わせ言語を利用します。
特徴
最新のsymfonyがDoctrineをデフォルトのORMとして採用し、Zend FrameworkでもDoctrineの利用を推奨しています。Ruby On Railsで採用されているActive Recordパターンをサポートしています。
アプリケーションとORMのやりとりはDQL(Doctrine Query Language)で行われます。DQLはJavaのHQL(Hibernate Query Language)に似た言語で、SQLに似た問い合わせ言語です。DQLはオブジェクト指向で記述でき、継承、ポリモーフィック、関連などを扱うことができます。
DoctrineにはRuby on Railsでも利用されているマイグレーション機能があり、データベーススキーマのバージョン管理を行うことができます。マイグレーション機能は、バージョン1.3と2.0どちらでも利用可能です。
キャッシュ機能を備えているため、トラフィックの多いサイトに適しているORMです。
実行例
以下にORMクラスを生成するコードと、実行例を記載します。
<?php // Doctrineライブラリの読み込み require_once(dirname(__FILE__) . '/lib/vendor/doctrine/Doctrine.php'); // クラスの自動読み込みを設定 spl_autoload_register(array('Doctrine', 'autoload')); // ORM用クラスの自動生成 $conn_id = 'doctrine'; $conn = Doctrine_Manager::connection('mysql://orm@192.168.0.40/orm', $conn_id); Doctrine_Core::generateModelsFromDb('models', array($conn_id), array('generateTableClasses' => true));
<?php // Doctrineライブラリの読み込み require_once(dirname(__FILE__) . '/lib/vendor/doctrine/Doctrine.php'); // クラスの自動読み込みを設定 spl_autoload_register(array('Doctrine', 'autoload')); spl_autoload_register(array('Doctrine_Core', 'modelsAutoload')); // 自動生成されたクラスの保存場所を指定 Doctrine_Core::setModelsDirectory('models/generated'); Doctrine_Core::loadModels('models'); // Doctrine全体の設定を行うためにマネージャを取得 $manager = Doctrine_Manager::getInstance(); // データベースへ接続 $conn = Doctrine_Manager::connection('mysql://orm@192.168.0.40/orm', 'doctrine');
<?php // 設定ファイルを読み込み require_once('bootstrap.php'); // Authorオブジェクトを生成 $author = new Author(); $random = rand(1, 10000); $author->name = 'username-'.$random; $author->password = 'password-'.$random; // Authorオブジェクトを保存 $author->save(); // AuthorオブジェクトのIDを取得 $id = array_shift($author->identifier()); // Authorオブジェクトを取得 $author = Doctrine_Core::getTable('Author')->find($id); // パスワードを変更して更新 $author->password = 'newpassword'.rand(1,100000); $author->save(); // Authorを削除 $author->delete();
Doctrineはあらかじめ稼働中のデータベーススキーマやスキーマを定義したYAMLファイルからクラスを生成しておく必要があります。スキーマが変更されるたびにクラスの生成を行います。
データの取得や保存には一切SQLを記述しないでオブジェクト指向によるメソッド呼び出しで行うことができます。1レコードが1オブジェクトとして扱えるので、データを削除する際や更新する際にはメソッドを呼ぶだけで更新できます。