The behavior you're observing is due to how the pluck() method interacts with Eloquent models in Laravel. Here's a breakdown of your questions and the recommended approach:
-
Why does
Model::query()->pluck('name', 'id')return the raw database values with the new class-basedname(): Attribute?The
pluck()method directly queries the database and retrieves the specified columns without instantiating the model objects. This means it bypasses any accessors, including the new class-based accessors. The old magic accessors (getNameAttribute()) were applied because they were part of the model's attribute retrieval process, whichpluck()does not trigger. -
Is this the intended behavior, or am I missing something about how
pluck()interacts with the newer Attribute accessors?Yes, this is the intended behavior. The
pluck()method is designed to be a lightweight way to retrieve specific columns directly from the database, which is why it doesn't apply any model accessors or mutators. -
What is the recommended or “best practice” way to retrieve transformed attribute values under the new accessor approach?
If you need to apply transformations defined in accessors, you should retrieve the models and then map over them to apply the accessor logic. Here's how you can do it:
$models = MyModel::all()->mapWithKeys(function ($model) { return [$model->id => $model->name]; });In the context of FilamentPHP, you can use this approach to ensure that the transformed values are used:
Forms\Components\Select::make('model_id') ->label('Status') ->relationship('modelRelationship', 'name') ->options(MyModel::all()->mapWithKeys(function ($model) { return [$model->id => $model->name]; }));This way, you ensure that the accessor logic is applied to the
nameattribute, as the models are fully instantiated and the accessors are invoked when accessing the attributes.
By using all() and mapWithKeys(), you ensure that the accessors are applied, and you still get a key-value pair suitable for options in a select component.