Blog: Don't Do This At Home #5: Use where() Instead Of filterBy()

The Propel Team – 20 March 2012

Can you spot the problem in the following snippet?

Firstly, this method can only be used if the query was created using the default class name. Remember: the developer can use an alias instead of the full model class name when creating a query:

This is useful when dealing with long classnames. Also, Propel automatically aliases a query when it is embedded into another one with useXXXQuery(). That means Propel may not recognize the column name Book.PublishedAt if the query was created using an alias. The correct way to implement a call to where() in a query method is to use ModelCriteria::getModelAliasOrName(), as follows:

Secondly, calling where($clause, $value) triggers a parsing of the $clause string. Propel looks for column names in the string to determine the binding type to use for the value. In this example, 'Book.PublishedAt' refers to a TIMESTAMP column, so Propel converts the $value to a timestamp string and binds it as a string. This clause parsing process uses regular expressions and has an impact on performance at runtime.

The alternative is to use the generated filterByXXX() method. When generating the query class, Propel knows the type of each column, and creates filter methods with the correct binding type baked in. Therefore, the execution of a filterByXXX() method requires no string parsing, and provides additional features. For instance, for date and time columns, the generated filter method allows for array values, which is especially useful in the filterByPublishedAtBetween() case:

And while we are at it, you don't have to name all your filter methods "filterBySomething". Propel uses this convention for column filters, but your custom filters should be named after the business rule they represent. So keep them as short and expressive as possible. In the BookQuery example, it's probably a better idea to rename filterByPublishedAtBetween($begin, $end) to publishedBetween($begin, $end). That way, you can create very expressive queries: