The best PHP ORM libraries, Doctrine and Propel. Last year I compared them to each other, and now it’s time to get a fresh look at how they have advanced in about a year – Is Doctrine still the better of the two?

This time, I’ll also look at the features of each in more depth.

Features

As mentioned in the earlier post, both Doctrine and Propel have quite similar basic feature set: They support all the usual CRUD operations you would expect, from creating new records to updating old ones.

Both can generate the model class PHP code for you, Propel based on XML and Doctrine based on YAML. Both support generating their respective markup from an existing database, though not to 100% accuracy – some more DB-specific and specialized things may not get cloned into the markup.

Advanced features

Both libraries support storing tree structures in the database using the nested set model. Doctrine’s nested set implementation supports storing multiple trees in the same table instead of just one.

Both also support validation of the data in the models and relations between models.

They also support single table inheritance, although in Doctrine this is known as concrete inheritance. Doctrine supports two other inheritance models: Simple, where all classes have the same columns, and column aggregation, which stores an additional type value in the table, allowing automatic instanciation of the correct model type when querying.

And here ends the shared features. All of the following things are features that only Doctrine has.

Behaviors: Doctrine supports applying various “behaviors” to your models, for example a Timestampable model automatically gets two columns: created_at and updated_at, which get a time when a row is first created and when it’s updated respectively.

Searching: Doctrine has a custom fulltext search engine.

Data fixtures and migrations. Caching, events, pagination, command line interface… you might say that Doctrine beats Propel hands down when it comes to more advanced features.

Ease of use

Documentation

The first thing is of course the documentation. Without decent documentation it’ll be difficult to use any library. Last year, Propel’s documentation was one of the main problems with it – and it still hasn’t gotten any better.

On the opposing side, the Doctrine team has been constantly improving their already superior documentation, and they are even working on a paperback Doctrine book. Documentation is a clear win for Doctrine.

Using the libraries

The first task you will have with both of the libraries is creating the model classes. Doctrine allows you to write simple YAML markup, or straight PHP code if you prefer it that way. If you use YAML, Doctrine has some methods that you can call in your own code, or you can download a command-line interface for building your models.

Propel’s approach to creating models requires you to write XML. To build your models from XML, you also need Phing. Personally I find XML more complex to write by hand than YAML, and requiring additional libraries is a bit of a hassle, unless you already use Phing for something else such as build automation.

Database operations

Basic CRUD operations are quite similar in both. However, there’s a big difference in the way more precise queries are done.

Propel uses a criteria/peer approach:

$c=new Criteria();$c->add(ExamplePeer::ID,20);//SELECT all "Example" models which have 20 as their ID and join all foreign tables.$items= ExamplePeer::doSelectJoinFoobar($c);

Doctrine’s approach is to use Doctrine_Query and a custom SQL dialect, DQL:

I think Doctrine’s approach lends itself better to the purprose. The code is also easier to read, as it flows more naturally. Propel’s version does take a bit less code.

Setting values on model classes is also a bit different: Doctrine uses magic properties, while Propel generates methods for setting and getting values. This gives Propel code the advantage of autocompletion in more IDE’s – as far as I know, only the latest versions of NetBeans can autocomplete Doctrine’s magic properties, thanks to their support of the @property PHPDoc annotation.

Conclusion

No matter how you look at it, Doctrine is better. Better docs, better features, and the community is active. Propel has gone forwards, but Doctrine has been going forwards at a much faster pace.

41 Responses to “Doctrine vs. Propel: 2009 update”

I never run into need of use this libraries. In the end, Zend_Db fulfil my needs. Syntax is very similar to Doctrine and supports also advanced tasks as table relationships (written in PHP, also on MyIsam) and cascade operations (on MyIsam too, but it is not atomic operation).

The question is, what benefit I could expect from using this libraries?

I think you do need to have a DB connection to test the models, but it’s not much of an issue: Since Doctrine supports SQLite, you can just create a dummy in-memory SQLite database in your tests, which works quite fine in my experience.

I think Doctrine is great, We’re currently running ZF, Doctrine and Dwoo and so far it’s a powerful mix !

Doctrine’s DQL language means you can optimize your queries just like you could in raw sql, it just takes some getting used to.

I still would like a more flexible system for reading yaml files and generating models and the database, currently your definition needs to be in one place and the models are generated in one place, it would be nice if you could specify multiple paths for the yaml files and then have inside the yaml a relative path to the directory the models should go.
Add a bit of analitics to know in which order the multiple models and database schema should be generated and it would be perfect.

“This gives Propel code the advantage of autocompletion in more IDE’s – as far as I know, only the latest versions of NetBeans can autocomplete Doctrine’s magic properties, thanks to their support of the @property PHPDoc annotation.”

Nice comparison, thanks. I never used Propel, but I did some experiments with Doctrine in combination with ZF in the last weeks. As the documentation is really detailed and full of code snippets it was quite easy to start and to achieve working results in a short time. In addition, the feature of YAML-schemas and fixtures in combination with the CLI interface is extremely useful and allowed me to set up automatic deployment to a dev-server using GIT-hooks and some simple scripts quite easily. I think for my next projects, I’ll definitely go for Doctrine.

This is a great comparison between the two. It may be a bit too early to ask you to compare a third advanced ORM that has just been released as beta on launchpad: http://launchpad.net/php-activerecord. However, we hope that in the future you’d might do another comparison of all three. We have a blog post about the release here: http://www.derivante.com/2009/05/19/php-activerecord-available-for-beta-testing/ where you can see just how easy it is to use. PHP ActiveRecord does not require you to use yaml/xml files like doctrine or propel. Instead, configuration is very quick and easy. Please have a look, thanks.

Outlet seems like a nice idea: Not having to inherit your models from a base class is a good thing. However, the code seems messy and doesn’t appear to follow any conventions.

Doctrine 2.0 is going to allow you to work without inheriting from Doctrine_Record, too, taking away the main “good thing” of Outlet.

Then, we have PHP ActiveRecord, which seems mostly a different way of doing the same with no special merits and the possible issue that it requires PHP 5.3. It doesn’t seem to follow common conventions regarding file organization, and will probably be a little tricky to get working with say Zend Framework’s autoloader, unlike Doctrine which works perfectly fine. It does have its own autoloader, though.

The code of PHP ActiveRecord does seem much cleaner than Outlet’s, though.

I’ll do a more formal example of AR and ZF integration in the days to come with a downloadable example. I suspect though that integration to CI/Cake/Symfony will be as easy as it was for Zend. The whole point of the MVC is that items are broken up into layers and one layer should not be dependent on another. It’s a whole lot easier than trying to replace Zend’s View with something like Smarty.

What about performances ?
Nobody seems to check this aspect of the comparison while in my opinion this should be one of the first things to compare…
So, anyone made deep benchmarks between these orms ?
Regards

I did a performance run on propel and doctrine and the difference is huge.

I someone is interested, i can provide scripts, maybe I am missing some setting. andrius.karpavicius.consulting at gmail dot com

Main table has 16 fields and 3578 records, related table has 25 fields and 599 records. Main table has two foreign keys to related table. In tests with pager, paging to 10’th page with 50 record’s per page.

This article, I feel, is substantially biased towards Doctrine. Write Propel schemas /only/ in XML? I don’t even know how to! I’ve been using YML the whole time, and that major oversight alone was enough to conclude that this article isn’t essentially the best to compare the two from.

It’s very unfortunate that this was the first article that came up on a Google search for a discussion of the differences between Propel and Doctrine.

You failed to do any sort of comparison of runtime efficiency, you have no discussion of the fully object-oriented query interface in Propel, and you have a flat-out false claim that Propel does not support behaviors! Have you ever used Propel!?

* Fulltext searches are a function of the database, not the ORM.

* Propel runs so much faster because it doesn’t have to parse this silly faux SQL.

I realize the comparison is a bit lacking, but in my defense both libraries are really big. However, I shall try to improve it in the future.

Fulltexts are indeed features of the database, but there are alternatives for fulltext like lucene which some prefer. Doctrine’s fulltext engine is a good alternative, as it works even if the DB doesn’t support fulltext itself.

“Faux SQL” aka DQL parsing is not very slow plus it can be cached.

Doctrine_Query is quite object oriented I think. It’s different from Propel’s, sure, but I think it functions rather well in any case.

I can’t help but wonder if there is a direct relationship between feature depth and performance in the case of any ORM tool? The newer or smaller ones seem to bill themselves as either easy or light weight. I came across what appears to be another entry into the PHP ORM fray in RedBean (http://www.redbeanphp.com/). I have not personally used it, but I thought I would throw it out for your consideration if you plan to perform future reviews.

I for one find Doctrine’s relationship requirement to be a dealbreaker. My database exists over and above the application that uses it. To require explicit application level relationships for a simple inner join is a waste of my time, and a dependency that doesn’t add to the efficiency of the app or the db. It’s just a necessary evil for Doctrine’s overly-engineered DQL.

Performance is also such a huge problem that I can’t say I want or need Doctrine ever. Propel has it’s issues, but I can’t say it’s ever forced me to add unnecessary code to my apps.

Currently I don’t use Propel, only Doctrine 1.2.x (MySQL 5.x)
The app is running as fast as a snail (or even slower): simple db schema, with dozen of models, with simple “DQLs”, couple of PITA relations for left joins (?) and this weekend I’m going to try Propel.

Anyway, thanks to jwage and the rest of the Doctrine crew. I appreciate their work, but hardly I’ll use it in my future projects.

I have used propel in multiple projects. I never had any issues with performance or fetching deeply nested objects using Propel.

One advantage that I would like to point out is that Propel is a port of the Java project “Apache Torque”. I brought my knowledge of Torque over to my PHP/Propel. (I did not even notice that the Propel documentation was lacking.)