Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

phpMick's avatar
Level 15

Eager loading an attribute.

Hi,

We have an accessor which calls a relationship. The accessor is used in a resource. When I hit the index page, this is going to n+1.

Can I eager load an accessor (on a collection) or have I completely lost the plot?

Thanks,

Mick

0 likes
14 replies
Nakov's avatar

When you pass the parameter to the resource you can eager load the relationship then:

UserResource::collection(User::with('posts')->get());

since you are not sharing any code, that's just an example above.

phpMick's avatar
Level 15

It's not a relationship. It's an accessor which calls a relationship.

phpMick's avatar
Level 15

@Sinnbeck I was hoping I could somehow load the accessor. It contains some iteration which I would like to avoid doing later.

I'm sure I have done this in a previous project.

Nakov's avatar

@phpMick you can if you add protected $appends = ['accessor_name']; on your model... but yet again you MUST use with to eager load the relationship that you use.

Sinnbeck's avatar

@phpMick I you are just getting 1 item you can use lazy eager loading in the accessor, but be aware that this wont work as expected if you are loading multiple items of the parent

phpMick's avatar
Level 15

@Nakov I don't think that is correct. Appends will add it to the list of attributes to get serialised but it won't actually load it. I'm using a resource so I specify which fields to include anyway.

phpMick's avatar
Level 15

So this is what we have:

Model:

 public function things(): HasMany 
{
//etc
}

public function getComplexThingsAttribute()
{
		$collection = $this->things;
		//complex iteration with things to make an array

		return $array;

}

ThingResource

  public function toArray($request): array
    {
  
      return [
		//other attributes
		$this->complexThings, // this needs to be already loaded here

		]
	}
Sinnbeck's avatar

@phpMick So you just load things. It was what @nakov suggested in his first post.

MyModel::with('things')->get();
phpMick's avatar
Level 15

@Sinnbeck

"I was hoping I could somehow load the accessor. It contains some iteration which I would like to avoid doing later."

Sinnbeck's avatar

@phpMick You will either need to do it always using protected $with on the model or call it when needed. But if the parent model is just 1 (first or find), you can use eager lazy loading

public function getComplexThingsAttribute()
{
       $this->loadMissing('things'); //load the relationship if it isnt loaded
		$collection = $this->things;
		//complex iteration with things to make an array

		return $array;

}

Please or to participate in this conversation.