I’ve been briefly comparing 3 leading ORMs and I wanted to share. I’ve left out Propel because I can’t get over the requirement of a seperate xml schema file.
1) PEAR DB_DataObject
- php 4
- Requires seperate schema file built by a script from an existing database. Actually, you don’t have to use a schema file, but since that requires DB_DataObject to query the database for metadata, it isn’t recommended for production use.
- Does not fully support table relationships since you must manually join tables in your queries using helper functions.
2) EZPDO
- php 5
- Very simple, yet powerful.
- Probably the slowest ORM. However a beta version uses the PDO DBAL.
- Like Doctrine, it uses its own SQL query language for portability.
- Able to automatically create tables from classes, but unlike Doctrine it can’t create classes from an existing database.
- No schema file. Table field data types and relationships defined in comments keeping the classes small and neat (but at the expense of some speed).
class Person extends Base {
/**
* Name of the author
* @var string
* @orm char(64)
*/
public $name;
/**
* Name of the author
* @var string
* @orm char(64)
*/
public $hair;
/**
* @var array of Pet
* @orm has many Pet
*/
public $pets = array();3) Doctrine
- php 5
- Fast since it uses PDO.
- Young - release candidate 1 due August 31. Documentation is incomplete and has errors.
- Like EZPDO, it uses its own SQL query language for portability. Raw SQL is an option though.
- Able to automatically create database tables from classes AND create classes from an existing database.
- No schema file. Table field datatypes and relationships are defined in object methods. Not as neat as EZPDO, but faster.
class Person extends Doctrine_Record
{
public function setTableDefinition()
{
$this->hasColumn('name', 'string', 20);
$this->hasColumn('hair', 'string', 20);
}
public function setUp()
{
$this->hasMany('Pet', array('local' => 'pet_id',
'foreign' => 'person_id',
'onDelete' => 'CASCADE'));
}
}All the ORMs handle insert and update in a similar simple way. However, Doctrine is a little less convenient when it comes to selecting records in my opinion:
DB_DataObject select
$person = new DataObjects_Person();
// or
$person = DB_DataObject::factory('Person');
$person->hair = 'red';
// A bonus of find() is that it returns the number a rows.
// However, find() does not return an array. You must call fetch() in a loop to get all records
$person->find()
while ($person->fetch())
{
…
}EZPDO select - maybe the easiest?
// $ezpdo = epManager::instance();
$person = $ezpdo->create('Person');
$person->hair = 'red';
$people = $person->find();
foreach ($people as $person)
{
…
}Doctrine select appears to require Doctrine SQL or optionally raw SQL. Note the CI-like query bindings and CI Active Recordish sql string building methods.
// $doctrine_connection = Doctrine_Manager::connection('mysql://root:dc34@localhost/test');
$people = $doctrine_connection->query('FROM Person where hair = ?', array(‘red’));
// or
$people = Doctrine_Query::create()->from('Person p')->where('hair','red')->execute();
// or
$query = new Doctrine_Query();
$people = $query->from('Person p')->where('hair','red')->execute();
foreach ($people as $person)
{
…
}I’ve briefly used DB_DataObject and Doctrine within CI.