$fields = $relation->getFields() is an array for a composite relation. The code just above handles that correctly when building the conditions:
if (is_array($fields)) {
// ... $record->readAttribute($fields[$i])
} else {
// ... $record->readAttribute($fields)
}
The reusable-cache key below it has no such guard:
$uniqueKey = $this->getUniqueKey(
$record,
$referencedModel,
[$intermediateModel, $parameters, $record->readAttribute($fields)]
);
readAttribute() takes a string, so a composite through-relation declared with reusable => true passes an array and fatals.
Expected
The cache key is built from every field the relation covers, the same way the conditions above it are.
Note
Even if the type error is only sidestepped, reading a single attribute for a composite relation would produce the same key for different records, so the reuse cache would return the wrong rows. The key has to include all the fields.
Not affected
Manager.php:1609 and :1734 reach readAttribute($fields) only inside an is_array() branch, so they are correct as they stand.
$fields = $relation->getFields()is an array for a composite relation. The code just above handles that correctly when building the conditions:The reusable-cache key below it has no such guard:
readAttribute()takes a string, so a composite through-relation declared withreusable => truepasses an array and fatals.Expected
The cache key is built from every field the relation covers, the same way the conditions above it are.
Note
Even if the type error is only sidestepped, reading a single attribute for a composite relation would produce the same key for different records, so the reuse cache would return the wrong rows. The key has to include all the fields.
Not affected
Manager.php:1609and:1734reachreadAttribute($fields)only inside anis_array()branch, so they are correct as they stand.