Skip to content

Model accessors always called when arraying a model #55067

Open
@mattmcdev

Description

@mattmcdev

Laravel Version

12.2

PHP Version

8.4.1

Database Driver & Version

No response

Description

All model accessors are called when calling toArray on a model, even if they aren't included in the array.

Consider the following:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Foo extends Model
{
    protected $visible = [
        'id',
        'name',
    ];

    protected function location(): Attribute
    {
        return Attribute::make(
            get: fn () => 'Paris',
        );
    }
}

When calling toArray getMutatedAttributes is always run and then filtered down to just the arrayable attributes.

Why does this matter ?

Because with a more complex Attribute accessor that relies on a relation, you introduce potential eager-loading issues when using API resource collections , e.g.

protected function timezone(): Attribute
    {
        return Attribute::make(
            get: fn () => $this->location->timezone,
        );
    }

Steps To Reproduce

  1. Create a model with an accessor that dumps or logs when run, but don't include it in visible/appends.
  2. Call toArray on the model and observe that the accessor was run.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions