Doctrine vs. Propel: 2009 update

May 16, 2009 – 7:13 am Tags: ,

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.


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


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:

$items = Doctrine_Query::create()
       ->from('Example e')
       ->where(' = ?', 20)

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.


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.

Share this:
  1. 42 Responses to “Doctrine vs. Propel: 2009 update”

  2. 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?

    By Srigi on May 16, 2009

  3. “Doctrine does not generate YAML for relations.”

    Doctrine will generate relations when importing from existing databases just fine.

    By jwage on May 16, 2009

  4. It does? Interesting… I must’ve been doing something wrong since it didn’t seem to do that for me.

    Thanks for pointing it out, fixed.

    By Jani Hartikainen on May 16, 2009

  5. Nice write up, I am currently thinking of implementing doctrine for the project I have just taken over, its good to know there is good docs for it :)

    How testable are Models created by doctrine? By that I mean can you test the Models without having to connect to the database.

    By Keith Pope on May 16, 2009

  6. 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.

    By Jani Hartikainen on May 16, 2009

  7. Cool not ideal but should be ok :) and your PHPUnit helper looks very useful too hehe

    By Keith Pope on May 16, 2009

  8. I also use Doctrine and switched from Propel some time ago. But there are some minor features which I am still missing with Doctrine. For example the code generation for getters/setters.

    By thedave on May 17, 2009

  9. 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.

    By Harro on May 17, 2009

  10. “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.”

    It works also in latest PDT and PhpED.

    By Anonymous on May 17, 2009

  11. There is an interesting project, called Outlet-ORM, for PHP. Have you seen it?

    By J Bruni on May 18, 2009

  12. Thanks for mentioning Outlet, J Bruni. It does indeed look interesting by a quick glance – will have to take a better look sometime!

    By Jani Hartikainen on May 19, 2009

  13. Does Doctrine support non-standard columns yet? I tried to play with it last year but it died trying to reverse-engineer my DB which uses geometry data types…

    By Alan Pinstein on May 19, 2009

  14. 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.

    By Mathias on May 20, 2009

  15. Zend_Db sucks! Start using Doctrine, and you’ll never back to Zend_Db!

    By yanoo on May 20, 2009

  16. I could get used to using this.

    By Tom Johnson on May 20, 2009

  17. 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: 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: 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.

    By Jacques Fuentes on May 20, 2009

  18. Some observations regarding Outlet ORM and PHP ActiveRecord..

    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.

    Disclaimer: I did not actually try using them (yet?)

    By Jani Hartikainen on May 20, 2009

  19. This is pretty easy to integrate to ZF. The AR does not interfere with the Zend_Loader at all, you can slide it in the bootstrap index.php like so:

    /* Zend Loader */
    require_once “Zend/Loader.php”;

    /* ActiveRecord */
    require_once ‘ActiveRecord/ActiveRecord.php’;
    // initialize ActiveRecord
    $cfg->set_model_directory(ROOT_DIR . ‘/application/models’);
    ‘development’ => ‘mysql://mydb:password@localhost/artest’));

    And inside of controllers/IndexController.php:

    view->book = Book::find(1);

    and inside your view script index/index.phtml:

    Today I read book->title?>… it was sweet.

    The last step is to create a Book.php in your /application/models:

    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.

    By Clay vanSchalkwijk on May 20, 2009

  20. 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 ?

    By youx on May 25, 2009

  21. Does search engine in the latest actually working? I’ve once used 1.0 branch and it didnt.

    By Apit on Jun 8, 2009

  22. 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. 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.

    Select * from main table
    propel 0.65384 sec.
    doctrine, hydration as array 1.24309 sec.
    doctrine, hydration as object 5.49193 sec.

    Select * from main table with pager
    propel 0.02704 sec.
    doctrine, hydration as array 0.08439 sec.
    doctrine, hydration as object 0.07002 sec.

    Join 2 tables
    propel 0.63045 sec.
    doctrine, hydration as array 2.2832 sec.
    doctrine, hydration as object 8.84054 sec.

    Join 2 tables with pager
    propel 0.01358 sec.
    doctrine, hydration as array 0.1838 sec.
    doctrine, hydration as object 2.43772 sec.

    Find by PK
    propel 0.00004 sec.
    doctrine, hydration as array 0.0067 sec.
    doctrine, hydration as object 0.01825 sec.

    By Andrius on Jun 12, 2009

  23. 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.

    By Tobias on Sep 9, 2009

  24. As far as I know, you don’t get YML with just Propel – Symfony lets you use YML with it, but not just plain Propel. Could be wrong too, old post.

    By Jani Hartikainen on Sep 9, 2009

  25. MySQL Workbench is a data modeling tool that replace DBDesigner. It has plugins to export data models as YAML for Doctrine, Propel, CakePHP.,208229

    By MySQL Workbench on Oct 4, 2009

  26. 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.

    * Object oriented query interfaces make it easier to build and modify query objects conditionally.

    By Jesse on Nov 6, 2009

  27. 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.

    By Jani Hartikainen on Nov 6, 2009

  28. 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 ( I have not personally used it, but I thought I would throw it out for your consideration if you plan to perform future reviews.

    By JJ on Dec 29, 2009

  29. 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.

    By Big Earl Madsen on Feb 24, 2010

  30. $example = Doctrine::getTable(‘Example’)->find(20);

    print $example->Foobar->whatever;
    print $example[‘Foobar’][‘whatever’];

    IF the relations are properly set up.

    and this feature can be set to be “on-demand”, so it won’t always load all the related objects, just and only when you request it

    By roland on Mar 16, 2010

  31. Hi,
    you could maybe write a 2010 version of Propel vs. Doctrine, as Propel 1.5 has changed almost completely the way you du CRUD operations with Propel :)

    Still, everything is BC.


    By Niklas Närhinen on May 27, 2010

  32. I might do an update when Doctrine 2.0 is more stable so there’s some news on their front too.

    By Jani Hartikainen on May 27, 2010

  33. NuSphere PhpED gives full code autocomplete feature for Doctrine. Even magic properties for database columns.

    By Las on Jun 6, 2010

  34. Actually, where is the comparison?

    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.

    By observer on Jun 11, 2010

  35. 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.)

    Hope this helps.

    By Anas Mughal on Oct 11, 2010

  36. i read your conclusions: i think you are correct

    By Rich on Feb 26, 2011

  37. If you’re looking for the latest comparison of the newest versions of Doctrine and Propel, you can find it here: Side by side: Doctrine2 and Propel 2.

    By Patrick on Apr 21, 2015

  1. 6 Trackback(s)

  2. May 16, 2009: Doctrine vs. Propel | CodeUtopia
  3. May 25, 2009: » Archive » Comparatif ORM PHP
  4. May 25, 2009: Comparatif ORM PHP |
  5. Jul 22, 2009: » Blog Archiv » Objektrelationales Mapping in PHP
  6. Sep 20, 2011: Doctrine Autocomplete ou Autocompletion | IT Blog
  7. Jul 21, 2013: Good comparison Doctrine vs Propel - PHP Questions - Developers Q & A

Post a Comment

You can use some HTML (a, em, strong, etc.). If you want to post code, use <pre lang="PHP">code here</pre> (you can replace PHP with the language you are posting)