As this question is rather old, I guess you already have had your try at writing an ORM yourself. Nonetheless, as I wrote a custom ORM two years ago, I would still like to share my experience and ideas.
As said I implemented a custom ORM two years ago and even used it with some success in small to medium sized projects. I integrated it in a rather popular CMS which at that time (and even now) lacks such ORM functionality. Furthermore, back then, popular frameworks like Doctrine didn´t really convince me. Much has changed since then and Doctrine 2 evolved in a solid framework, so, if I now had the choice between implementing my own ORM or using one of the popular frameworks like Doctrine 2 for production use, this would be no question at all - use the existing, stable solutions. BUT: implementing such a framework (in a simple manner) was a very valuable learning exercise and it helped me a lot in working with larger open source ORMs, as you get a better understanding for the pitfalls and difficulties associated with object relational mapping.
It is not too difficult to implement basic ORM functionality, but as soon as mapping of relationships between objects come into play, it gets much, much more difficult/interesting.
How did I get started?
What got me hooked was Martin Fowlers book Patterns of Enterprise Application Architecture. If you want to program your own ORM or even if you are just working with some ORM framework, buy this book. It is one of the most valuable resources that cover many of the basic and advanced techniques regarding the field of object relational mapping. Read up on it, you get many great ideas on the patterns behind a ORM.
Basic Architecture
I decided if I would like to use rather an Active Record approach or some kind of Data Mapper. This decision influences on how the data from the database is mapped to the entity. I decided to implement a simple Data Mapper, the same approach as Doctrine 2 or Hibernate in Java uses. Active Record is the approach of the ORM functionality (if you can call it so) in Zend Framework. Active Record is much simpler then a Data Mapper, but also much more limited. Read up on these patterns and check the mentioned frameworks, you get the difference pretty fast. If you decide to go with a Data Mapper, you should also read up on PHPs reflection API.
Querying
I had the ambitious goal to create my own query language, much like DQL in Doctrine or HQL in Hibernate. I soon abondoned that, as writing a custom SQL parser/lexer seemed way to complicated (and it really is!). What I did was to implement a Query Object, in order to encapsulate the information which table is involved in the query (thats important as you need to map the data from the database to the relevant classes for each table).
Querying for an object in my ORM looked like this:
public function findCountryByUid($countryUid) {
$queryObject = new QueryObject();
$queryObject->addSelectFields(new SelectFields('countries', '*'))
->addTable(new tx_persistenceTable('countries'))
->addWhere('countries.uid = "' . intval($countryUid) . '"');
$res = $this->findByQuery($queryObject);
return $res->getSingleResult();
}
Configuration
Normally, you also need to have some kind of configuration format, Hibernate uses XML (among others), Doctrine 2 uses PHP annotations, EZComponents uses PHP arrays in its Persistent Object component as config format. Thats what I used, too, it seemed like a natural choice and the CMS I worked with used the PHP configuration format, too.
With that configuration, you define
- which table gets mapped to which class
- what fields should get mapped to the class instance
- what type the fields of the table have (int, string, etc.)
- the relations between the entities (e. g. a User class has a reference to a UserGroup class)
- etc.
And thats the information you use in your Data Mapper to map the DB result to objects.
Implementation
I decided to go with a strong test driven approach, because of the complex nature of writing a custom ORM. TDD or not, writing many, many unit tests is a really good idea on such a project. Apart from that: get your hands dirty and keep Fowlers book close. ;-)
As I said it was really worth the effort, but I wouldn´t want to do it again, much because of the mature frameworks that exist nowadays.
I don´t use my ORM anymore, it worked, but lacked many features, among others: lazy loading, component mapping, transaction support, caching, custom types, prepared statements/parameters etc. And it´s performance wasn´t good enough for using it in large scale projects.
Nonetheless, I hope I could give you some starting points in the field of ORM, if you didn´t knew them already. ;-)