-
Notifications
You must be signed in to change notification settings - Fork 11.5k
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();