As per this StackOverflow question, using $this->attributes['items'] instead seems to work. Still interested in understanding what's going on.
Sep 29, 2023
6
Level 1
Relationship property undefined in accessor
Hi,
I have the following:
Controller:
public function show(Source $source) {
$source->load([
'items.image',
]);
return view('source.show', [ 'source' => $source ]);
}
Model
public function items() {
return $this->hasMany(Item::class);
}
public function getDependenciesAttribute() {
$itemFileNames = $this->items->whereNotNull('dependency_filename')->pluck('dependency_filename');
if ($itemFileNames->isEmpty()) {
return collect();
}
return Source
::where(fn($query) =>
$query->whereHas('models', fn ($query) => $query->whereIn('filename', $itemFileNames))
->orWhereHas('items', fn ($query) => $query->whereIn('filename', $itemFileNames))
)
->where('id', 'IS DISTINCT FROM', $this->patches_source_id)
->where('id', 'IS DISTINCT FROM', MAIN_SOURCE_ID)
->orderBy('title')
->get();
}
This works as it should. It's sort of a complex query, but that's beside the point. Now, I wanted to rewrite it to return an Attribute instead, in order to make use of caching:
public function dependencies(): Attribute {
$itemFileNames = $this->items->whereNotNull('dependency_filename')->pluck('dependency_filename');
if ($itemFileNames->isEmpty()) {
return collect();
}
return Attribute::make(
get: fn () => Source
::where(fn($query) =>
$query->whereHas('models', fn ($query) => $query->whereIn('filename', $itemFileNames))
->orWhereHas('items', fn ($query) => $query->whereIn('filename', $itemFileNames))
)
->where('id', 'IS DISTINCT FROM', $this->patches_source_id)
->where('id', 'IS DISTINCT FROM', MAIN_SOURCE_ID)
->orderBy('title')
->get()
);
}
but that gives me Undefined property: App\Models\Source::$items on this line:
$itemFileNames = $this->items->whereNotNull('dependency_filename')->pluck('dependency_filename');
I don't understand why this is happening, and indeed if I try to dump $this->items just before this line it dumps a Collection of Items. Dumping the exact same expression also works as expected.
Please or to participate in this conversation.