-
Notifications
You must be signed in to change notification settings - Fork 11.7k
Description
Laravel Version
11.42.0
PHP Version
8.4.3
Database Driver & Version
No response
Description
Define a custom attribute with a convoluted name using the Attribute syntax:
Example:
protected function foo1Bar(): Attribute
{
return Attribute::make(
get: fn () => 'yay',
);
}Accessing a custom attribute is internally done by a snake-to-camel case conversion. So this means both foo1_bar and foo_1_bar will yield the expected value.
However, some features in Eloquent do the inverse by calling upon the attribute cache ($getAttributeMutatorCache): a camel-to-snake case conversion. This means that foo1Bar now only translates to foo1_bar, and not anymore to foo_1_bar even though its value would get returned when retrieving it.
echo $model->foo1_bar; // "yay"
$model->append('foo1_bar');
$model->toArray(); // Works fine.
echo $model->foo_1_bar; // "yay"
$model->append('foo_1_bar');
$model->toArray(); // Call to undefined method Model::getFoo1BarAttribute() On the contrary, when resorting back to the good old getFoo1BarAttribute() everything works as expected for both foo1_bar and foo_1_bar.
protected function getFoo1BarAttribute()
{
return 'yay';
}echo $model->foo1_bar; // "yay"
$model->append('foo1_bar');
$model->toArray(); // Works fine.
echo $model->foo_1_bar; // "yay"
$model->append('foo_1_bar');
$model->toArray(); // Works fine.So, because of internal two-way case conversions to support the newer attribute syntax some unexpected and disfunctional ambiguity gets introduced.
I think both syntaxes (Attribute vs getXXXAttribute()) should behave equally. But I'm not quite sure how to proceed with this. Should foo_1_bar get blocked for access to prevent this kind of expectations further down the line? Or should it also resolve properly when doing the camel-to-snake conversion? Or...?
Steps To Reproduce
protected function foo1Bar(): Attribute
{
return Attribute::make(
get: fn () => 'yay',
);
}$model->append('foo_1_bar');
$model->toArray();