Is it preferable to define the fields to be retrieved during a `contain()`?

In the case of DB structures with a lot of associations and therefore a lot of joins (contain()), I quickly find myself dealing with object instances having a lot of fields and a lot of nesting.
I’m wondering whether this is a good thing or whether it’s better to define the fields to be retrieved when using contain().

For example, when I do $query->contain('Model.AnotherModel.AnotherModelAgain') I end up with an instance with 4 levels of nesting with each time all the fields for each model.

I don’t need all these fields, but the aim is to simplify reading the code.

In fact :

$query->contain('Model.AnotherModel.AnotherModelAgain');

is simpler than :

$query->contain([
	Model' => [
		fields' => ['field_1', 'field_2', 'field_3'],
		[
			'AnotherModel' => ['field_1', 'field_2'],
			[
				'AnotherModel' => ['field_1', 'field_2', 'field_3'],
			]
		]
	]
]);

but is it a problem in terms of performance and/or security?

From a pure SQL perspective selecting only the fields needed is of course advantages because your query runs faster. The ORM is also aware of this, so the generated entity inside your associations will only contain those fields selected.

I’d say go for it if the performance optimizations are worth it for you. I have not yet tested the impact of this in my apps but I just never cared about this since it seems “micro-optimizational” - especially if you may adjust those Models in the future and wonder yourself why the new field is not there.


You can leverage custom finders to extract that ->contain() part into the table class so its easier to re-use it (and easier on the eyes in the controller :wink: )

OK, thank you.

A side question:

I often use contain() inside the callback ModelTable::beforeFind() in order to simplify controller inheritance.
Doing an automatic join like that means that I don’t have to rewrite any code in the extended controller.

Do you think this is a good thing or a bad thing?

Well if you rarely have the situation where you need data without that association loaded then sure, this seems fine.

I never had this situation come up but I guess this highly depends on the DB schema.