Blog: Propel 1.5.3 Released

The Propel Team – 16 August 2010

Even during the summer, the Propel team is at work for improving your favorite ORM. With 19 bug fixes and 7 enhancements, here comes the latest minor release of the 1.5 branch. Propel 1.5.3 has an impressive changelog, but it’s still the same story: it’s backwards compatible, more robust, performs better, and offers a handful of new features.

What’s new in this release is that more and more people actively contribute to the Propel core. Whether by opening bug reports, writing unit tests, patches or documentation, they all helped to deliver a great release in a very short timeframe. Don’t hesitate to thank them all in the comments ; if you don’t already follow the project timeline, you can find their names in the changelog.

Let’s look closer at some of the enhancements brought by Propel 1.5.3.


You’re now used to retrieving ActiveRecord objects or collections using the generated Query classes. But what if you just need one or two calculated columns? In that case, hydrating an entire object is overkill. Propel 1.5.3 introduces the ModelCriteria::select() query modifier. It tells the query to return an array of columns rather than ActiveRecord objects. It’s very intuitive and easy to use: just specify which columns you need in an array passed as argument to select(), terminate the query with find(), and you’re done:

$books = BookQuery::create()
  ->select(array('Id', 'Title', 'Author.LastName'))
// array(
//   array('Id' => 123, 'Title' => 'Pride and Prejudice', 'Author.LastName' => 'Austen'),
//   array('Id' => 456, 'Title' => 'War and Peace', 'Author.LastName' => 'Tolstoi')
// )

You can mix columns from the main object and from joined classes – Propel will deal with any column name present in the query. If you need only one row, terminate with findOne() instead of find(), and you’ll get an array instead of an array of arrays:

$books = BookQuery::create()
  ->select(array('Id', 'Title', 'Author.LastName'))
// array('Id' => 123, 'Title' => 'Pride and Prejudice', 'Author.LastName' => 'Austen')

If you need only a single column, use a column name instead of an array of column names as argument to select(). Propel will the be smart enough to return scalars rather than arrays:

$books = BookQuery::create()
// array('Pride and Prejudice', 'War and Peace')

$books = BookQuery::create()
// 'Pride and Prejudice'

There is more to select() than the few examples illustrated here – fortunately, this new feature is extensively documented. Head to the ModelCriteria reference for details.


If you need to add all the columns of a model in a GROUP BY clause (PostgreSQL forces you to do that when you use aggregate functions in addition to a model object), use the new groupByClass() shortcut: with a model class name as sole argument, it will expand into one GROUP BY for each column:

$authors = AuthorQuery::create() 
  ->withColumn('COUNT(Book.Id)', 'NbBooks')
// groupByClass('Author') translates to SQL as:
// GROUP BY author.ID, author.FIRST_NAME, author.LAST_NAME

Check the documentation for this new feature in the ModelCriteria reference.

Behaviors Can Now Create Classes

Behaviors are no longer limited to the existing model classes (ActiveRecord, Peer, Query and TableMap classes). Starting with Propel 1.5.3, you can let a behavior write an entire new class based on the model. This can be very useful to create proxy classes for your model classes, for instance to integrate Propel with Zend_AMF in order to build a Flex front-end.

Check the how-to for this feature in the behaviors documentation.

Various Optimizations

Propel 1.5.3 benefits from various optimizations that should make your apps a little snappier at runtime, including:

  • Nested Sets Optimization: If you added crafted an index for the left column, queries for the branch or the descendants of a given node will now take advantage of it (cf. #1034).
  • Getters for related objects using a composite foreign key now take advantage of the instance pooling (cf. #1011)


How to upgrade? You have three choices – It’s your call: