Closed webstackdev closed 6 years ago
The forum had to be removed because of GDPR.
No, what you are doing is not directly possible. The main model can only control eager loading for the 2nd and 4th model. However, the 2nd model controls eager loading for 3rd model and the 4th model controls eager loading for the 5th model. If you really need the whole thirdModel and fifthModel functionality you could use with() in the constructor of secondModel and fourthModel respectively.
I would be very weary at doing nested eager loading, though. For starters it’s slow and consumes a lot of memory. FOF doesn’t use a smart record mapper to create objects as needed (I tried exploring that option but the way Joomla handles database cursors doesn’t lend to that). Concrete models are created for every record. PHP objects are far from being lightweight. Nor only they consume tons of memory, but the creation and destruction of thousands of models triggers some rather nasty effects on PHP’s garbage collector.
On top of that, having to put yourself in that position is a “smell” in two ways.
First, it’s a sign that there is over-normalization of the data. For example, a typical problem is having invoice rows in a separate table to the invoice proper. This is wrong because you will never address an invoice row outside the context of its invoice. This is best handle in a “noSQL” approach, something MySQL only added in 5.6 and not very well supported inside Joomla. A simple workaround is storing a JSON document and mapping it to objects, if necessary, with custom code. It’s a bit of a kludge though so I can definitely see why using a separate table may still be appealing (and why I used that approach for my ticket system, for example).
The other “smell” is that you only need specific information from the leaf models which might be better provided by a helper. Depending on the use case you might do lazy loading or you might collect all the key values, array_unique them and do a quick database query to fetch relevant information. For example, in my ticket system I am using a helper to get user information. The additional queries were adding less overhead (memory and CPU) than eager loading user information from the ticket posts rows.
Relations and models are tools. They are not fetishes. If they are not the right tool for the job you don’t have to use them. If unsure, you can try eager loading the thirdModel from the secondModel and profile your application. Then try using a helper instead and see if that helps with the performance.
Hi Nicholas,
Thanks for taking time to write a detailed answer. I'm enjoying working with the FOF framework, it's a significant improvement over Joomla! MVC imo. The normalization in my domain model is being driven by other considerations, so I'll look at the other approaches.
I followed the link for questions / discussion on the main wiki page to the FOF Google Groups. That group is not on Google any longer, and a search for "Akeeba" in Google Groups only turned up Joomla! general development groups. If this is more appropriate in the Joomla! group, I'll ask there.
Is there a way to eager-load relations-at-a-distance? e.g. if I have a highly normalized data model that is pulling through a model:
mainModel
|--> secondModel --> thirdModel
|--> fourthModel --> fifthModel
And I want to get a property from both
thirdModel
andfifthModel
from a view tied tomainModel
, is there any way to eagerly load that relationship besides overridingbuildQuery
? From experimenting and looking through the code, it seems like I'm limited to eagerly loading justsecondModel
andfourthModel
usingwith()
, but I'm not sure.