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

nexxai's avatar
Level 37

Appending data to a relation sometimes

Ok I have what I think is a pretty normal question but maybe I just don't Get It™.

Let's say I have two models Parent and Child in a HasMany / BelongsTo relationship. Let's also say that there is an Eloquent Attribute on the Child model called fullName. Finally, let's say that I don't always want fullName to be available when the model is returned, but rather only in certain instances. That rules out adding fullName to the $appends array on the model.

For example, let's create a method on Parent called all_family_names() that returns itself plus all of its children.

In a perfect world, I'd do something like this:

public function all_family_names(): self
{
   return self::with('child')
      ->append('child.fullName')
      ->get();
}

but obviously that won't work, because append() only works on the original, top level model, and says that "getchild.fullNameAttribute" doesn't exist (naturally).

Ok then, what about something like this:

public function all_family_names(): self
{
   return self::with('child.fullName')
      ->get();
}

Of course, that's not going to work either because fullName isn't a relationship, but an attribute.

Finally, how about something like:

public function all_family_names(): self
{
   return self::query()
      ->with(['child' => function($query) {
         $query->append('fullName');
      )
      ->get();
}

No dice there either because the $query in this instance is a database builder, not an Eloquent builder, so append() doesn't exist.

Can anyone provide some guidance as to how I'd go about appending these "computed properties" only in certain instances? I can't imagine I'm the first one to have these problems but I can't find any documentation online that shows how to accomplish what I'm trying to do (although, it's very possible that I just don't know the right search term of what I'm really looking for).

0 likes
4 replies
LaryAI's avatar
LaryAI
AI
Best Answer
Level 58

To achieve the desired behavior of appending a computed property to a relation only in certain instances, you can manually append the attribute to each related model after you have retrieved the collection. Here's how you can modify the all_family_names method to do this:

public function all_family_names()
{
    // Retrieve the parent model with its children
    $parent = $this->load('children');

    // Iterate over each child and append the fullName attribute
    $parent->children->each(function ($child) {
        $child->append('fullName');
    });

    return $parent;
}

In this solution, we're using the load method to eager load the children relationship. Then, we use the each method to iterate over the collection of children and append the fullName attribute to each Child model.

Please note that the relationship method name is assumed to be children based on the plural form of Child. If your relationship method is named differently, you should replace 'children' with the actual method name.

Also, ensure that the fullName attribute is properly defined in your Child model using an accessor, like so:

class Child extends Model
{
    // ...

    public function getFullNameAttribute()
    {
        // Assuming you have 'first_name' and 'last_name' columns
        return $this->first_name . ' ' . $this->last_name;
    }
}

This way, the fullName attribute will be appended to the Child model instances only when you call the all_family_names method on the Parent model, and not every time you retrieve Child model instances.

nexxai's avatar
Level 37

@LaryAI For now I'll take Lary's answer, but this feels like an N+1 problem. If anyone has a better solution, I am definitely listening.

Please or to participate in this conversation.