sfPropelFinder becomes DbFinder - Announcing 1.0 release

The sfPropelFinder plugin, which I've told you about a lot lately, has recently been renamed to DbFinder. This emphasizes the fact that the plugin is not Propel-specific anymore, and that you can use it with Doctrine without any change in the API.

Also, I have released a version 0.9 of the plugin today, which marks the 100% coverage of the API with both the Propel and the Doctrine adapters. That's right, now any piece of code using DbFinder will work seamlessly, whatever the ORM you use in symfony.

Take the following code, for instance:

// Look in the Article model
// For objects where the author object related to the article has $nickname for nickname
// Hydrated with related translation in the current culture and category
// And put the result into a pager implementing sfPager for easy display in a web page
$pager = DbFinder::from('Article')->
  where('Author.Nickname', $nickname)->
  with('I18n', 'Category')->
  paginate($currentPage = 1, $maxResultsPerPage = 10);


Getting the same result with either Propel or Doctrine takes considerably more code.

To be honest, the Doctrine coverage is only 99%, since there is still an issue with sfDoctrineFinder::withColumn() when dealing with a calculated column - and this is something that requires Doctrine 1.0 to be fixed. The current Doctrine adapter is based on sfDoctrinePlugin and Doctrine 0.11. But as soon as Doctrine 1.0 is released, withColumn() will be updated to work exactly the same as with Propel.

This release can be considered as a 1.0 beta 1 - meaning I'll probably not add more features before releasing a stable version. I'll work on performance and edge cases if bugs are reported, so you are encouraged to download the plugin, test it, and give me as much feedback as you can.

Possibly related posts (automatically generated):

16 Comments so far

  1. stefan on August 28th, 2008

    Excellent! I have recently started using DbFinder, and I love it. Perhaps this will finally make me feel good enough about some of my plugins to actually release them in the wild. Not being able to support both Propel and Doctrine so far was one of the main reasons holding me back from publishing them.

    Now I just need time to rewrite my plugins to DbFinder :)

  2. Thomas R. on August 28th, 2008

    This is a great news !

    One question : How does the plugin manage specific feature such as NestedSet or Mixin/Behavior ?

  3. Dexter Williams on August 28th, 2008

    Hey Francois,

    Congrats. Do you plan to adapt more of your plugins to this excellent solution? (like sfSimpleForum?)

    Keep up the good work, Dexter

  4. Francois Zaninotto on August 28th, 2008

    @Dexter: Yes I do, but there are many dependencies (feeds, sfGuard, moderation), so I have to start by the ones that don't rely on other plugins first.

  5. Yuriy Voziy on August 28th, 2008

    Where can I find full API for this fantastic plugin?

  6. Neonard0 on August 29th, 2008

    Yahooo!!!!!

  7. rioka on August 29th, 2008

    Really an excellent work!

    No troubles with symfony 1.0; anyway, I can't get int installed with symfony 1.1.1, is it true or am I missing something?

    Here is the output for symfony 1.1.1

    [...]

    sfPearFrontendPlugin ...done: 46,129 bytes sfPearFrontendPlugin symfony/DbFinderPlugin requires package "symfony/symfony " sfPearFrontendPlugin (version >= 1.0.0, version <= 1.1.0), installed version is sfPearFrontendPlugin 1.1.1

  8. Francois Zaninotto on August 29th, 2008

    @Yuryi: follow the second link given on this post and click on the "README" tab of the plugin's page.

    @rioka: My bad, I packaged with 1.1.0 max... The next release will solve this. In the meantime, try an svn checkout.

  9. Mark Quezada on August 29th, 2008

    Nice work Francois! I have yet to use DBFinder seperately in a project, but I have seen the updates to sfSimpleBlog and I like the syntax.

    Don't you think it's funny though, that now we're writing an abstraction layer for our database abstraction layers? I saw some of your stats on a previous post, but I'm curious to know what kind of performance overhead this adds.

  10. Francois Zaninotto on August 29th, 2008

    @Mark: If it disturbs you to see DbFinder as an abstraction layer, then don't look at it that way. If you're used to Propel alone, then DbFinder is just a class that provides a simpler API to tell Propel how to retrieve objects.

    The overhead depends on the amount of "magic" you ask the finder to do. For simple "where()" clauses, it is negligible; for complex joins, it's a little more, but overall it is much less overhead than what Doctrine, for instance, adds on top of PDO at runtime.

    And I won't go again into the debate "better tools/worse performance". If you ever did some development and had to have a client pay for it, you know that the time you spend writing code costs much more than the time the server takes to execute it. And if DbFinder adds a 1% overhead on top of Propel, it is very unlikely that it will force you tu upgrade your servers...

  11. slantedview on August 29th, 2008

    I just started playing with dbFinder, and so far I like it and really like the custom Propel hydration. Already though I'm coming across situations that I'm not sure dbFinder can handle.

    For example, say I have Article, Comment and User tables where an Article has one Comment and User (just for example) and a Comment can also have one User. I'm not sure how to write one dbFinder call to join Article and Comment and give me the User for the Article AND the User for the Comment. Is this possible?

    $this->article = DbFinder::from('Article')-> with('Comment')-> with('User')-> findOne();

    This would of course join the User to the Article. How could I do another User join for the Comment?

  12. slantedview on August 29th, 2008

    Sorry for the double post. I also wanted to include what the SQL should roughly be for the scenario give above:

    select ... from article, comment, user as article_user, user as comment_user where article.comment_id = comment.id and article.user_id = article_user.id and comment.user_id = comment_user.id

  13. Francois Zaninotto on August 29th, 2008

    slantedview: You'd have to call a join() before the with() where you specify which fields should be used for the relationship (Comment.user_id, User.id) and that should work.

  14. slantedview on August 29th, 2008

    Francois: Thanks for the followup.

  15. Cristi on October 8th, 2008

    How can we update a record with a custom criteria ? Is this posible? eg: ...->set(...)->add(BillPeer::UPDATED_AT, BillPeer::UPDATED_AT.'=now()', Criteria::CUSTOM)

  16. hanf on October 22nd, 2008

    is withColumn issue solved yet?