What is the best way of working with calculated fields of Propel objects?
Say I have an object ‘Customer’ that has a corresponding table ‘customers’ and each column corresponds to an attribute of my object. What I would like to do is: add a calculated attribute ‘Number of completed orders’ to my object when using it on View A but not on Views B and C.
The calculated attribute is a COUNT() of ‘Order’ objects linked to my ‘Customer’ object via ID.
What I can do now is to first select all Customer objects, then iteratively count Orders for all of them, but I’d think doing it in a single query would improve performance. But I cannot properly ‘hydrate’ my Propel object since it does not contain the definition of the calculated field(s).
How would you approach it?
There are several choices. First, is to create a view in your DB that will do the counts for you, similar to my answer here. I do this for a current Symfony project I work on where the read-only attributes for a given table are actually much, much wider than the table itself. This is my recommendation since grouping columns (max(), count(), etc) are read-only anyway.
The other options are to actually build this functionality into your model. You absolutely CAN do this hydration yourself, but it’s a bit complicated. Here’s the rough steps
However, this isn’t much better than what you’re talking about already. You’ll still need N + 1 queries to retrieve a single record set. However, you can get creative in step #3 so that N is the number of calculated columns, not the number of rows returned.
Another option is to create a custom selection method on your TablePeer class.
Here’s an example of this approach
There may be other solutions to your problem, but they are beyond my knowledge. Best of luck!