/ Quick Tips

How to display a model's appends in Laravel API Resources

How to display a model's appends in Laravel API Resources

Eloquent's Resource classes are flexible enough with conditional attributes and loading relationships but what if you want that same functionally for the appends of the model you are working with?

tl;dr Set $appends to public on the model. Use $this->when(in_array('APPEND_NAME', $this->appends), callback) on the resource level

Why this is important

The API Resource is only meant to be used as a last layer between your data and your API responses; thus it's not supposed to do any heavy lifting or create logic or complexity on its own.

The easy implementation

Just treat it like any other attribute of the model by adding it to the array.

class User extends Model
{
	public function getFullNameAttribute()
	{
    	return "{$this->first_name} {$this->last_name}";
	}
}

class User extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'full_name' => $this->full_name, // here's is the attribute
            'email' => $this->email,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

This works good when you are fine with adding it to every response and your accessor doesn't have any complex or expensive to run logic.

It's basically the equivalent of using the model directly and setting the protected $appends = [ 'full_name']; property on the model to always append the full_name to the model.

My solution

Set the $appends property to public on the model:

class User extends Model
{
	public $appends = [];
}

This allows you to do the following:

class User extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'full_name' => $this->when(in_array('full_name', $this->appends),
            	fn () => $this->full_name), // here's is the attribute
            'email' => $this->email,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

Voilà! Problem solved.

Using this approach you will have the benefit of only adding those computed properties when needed.

If you call $user->append('full_name') it will be later added to the resource array, not every time.

This is also particularly useful when you are doing some heavier computation on the attribute method like fetching some data from other services or database queries.

BONUS!

Quick tip: when writing Resource classes for you models one useful feature if you're using an IDE like PhpStorm is to add a phpdoc @mixindirective at the top of the class. This will help autocomplete all the Model's methods and properties on your resource class so no more typos or having to double check variable and method names

/**
 * @mixin \App\Models\User
 */
class User extends JsonResource
{
    public function toArray($request)
    {
       ... // Everything from the User class will be autocompleted
    }
}