Skip to content

Commit 1e5e54f

Browse files
committed
Merge branch '12.x' into fix/attribute-accessor-arrayable
2 parents 77e34d3 + fa0295c commit 1e5e54f

File tree

1 file changed

+25
-32
lines changed

1 file changed

+25
-32
lines changed

src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
use ReflectionNamedType;
4343
use RuntimeException;
4444
use Stringable;
45+
use Throwable;
4546
use ValueError;
4647

4748
use function Illuminate\Support\enum_value;
@@ -221,8 +222,11 @@ public function attributesToArray()
221222
$attributes = $this->getArrayableAttributes()
222223
);
223224

224-
// Important: derive mutated attributes *only* from the arrayable keys
225-
$mutatedAttributes = $this->getArrayableMutatedAttributes($attributes);
225+
$mutatedAttributes = array_values(
226+
array_filter(array_keys($attributes), function ($key) {
227+
return $this->hasAnyGetMutator($key);
228+
})
229+
);
226230

227231
$attributes = $this->addMutatedAttributesToArray(
228232
$attributes, $mutatedAttributes
@@ -690,7 +694,13 @@ public function hasAttributeGetMutator($key)
690694
return static::$getAttributeMutatorCache[get_class($this)][$key] = false;
691695
}
692696

693-
return static::$getAttributeMutatorCache[get_class($this)][$key] = is_callable($this->{Str::camel($key)}()->get);
697+
try {
698+
$attribute = $this->{Str::camel($key)}();
699+
700+
return static::$getAttributeMutatorCache[get_class($this)][$key] = is_callable($attribute->get);
701+
} catch (Throwable $e) {
702+
return static::$getAttributeMutatorCache[get_class($this)][$key] = false;
703+
}
694704
}
695705

696706
/**
@@ -755,8 +765,7 @@ protected function mutateAttributeForArray($key, $value)
755765
{
756766
if ($this->isClassCastable($key)) {
757767
$value = $this->getClassCastableAttributeValue($key, $value);
758-
} elseif (isset(static::$getAttributeMutatorCache[get_class($this)][$key]) &&
759-
static::$getAttributeMutatorCache[get_class($this)][$key] === true) {
768+
} elseif ($this->hasAttributeGetMutator($key)) {
760769
$value = $this->mutateAttributeMarkedAttribute($key, $value);
761770

762771
$value = $value instanceof DateTimeInterface
@@ -2440,20 +2449,6 @@ public function getMutatedAttributes()
24402449
return static::$mutatorCache[static::class];
24412450
}
24422451

2443-
protected function getArrayableMutatedAttributes(array $attributes): array
2444-
{
2445-
$keys = array_keys($attributes);
2446-
2447-
if ($keys === []) {
2448-
return [];
2449-
}
2450-
2451-
// Only consider keys that are actually arrayable *and* have a mutator
2452-
return array_values(array_filter($keys, function ($key) {
2453-
return $this->hasAnyGetMutator($key);
2454-
}));
2455-
}
2456-
24572452
/**
24582453
* Extract and cache all the mutated attributes of a class.
24592454
*
@@ -2466,7 +2461,9 @@ public static function cacheMutatedAttributes($classOrInstance)
24662461

24672462
$class = $reflection->getName();
24682463

2469-
static::$getAttributeMutatorCache[$class] = (new Collection($attributeMutatorMethods = static::getAttributeMarkedMutatorMethods($classOrInstance)))
2464+
$attributeMutatorMethods = static::getAttributeMarkedMutatorMethods($classOrInstance);
2465+
2466+
static::$getAttributeMutatorCache[$class] = (new Collection($attributeMutatorMethods))
24702467
->mapWithKeys(fn ($match) => [
24712468
lcfirst(static::$snakeAttributes ? Str::snake($match) : $match) => true,
24722469
])
@@ -2501,18 +2498,14 @@ protected static function getAttributeMarkedMutatorMethods($class)
25012498
{
25022499
$instance = is_object($class) ? $class : new $class;
25032500

2504-
return (new Collection((new ReflectionClass($instance))->getMethods()))->filter(function ($method) use ($instance) {
2505-
$returnType = $method->getReturnType();
2506-
2507-
if ($returnType instanceof ReflectionNamedType &&
2508-
$returnType->getName() === Attribute::class) {
2509-
if (is_callable($method->invoke($instance)->get)) {
2510-
return true;
2511-
}
2512-
}
2513-
2514-
return false;
2515-
})->map->name->values()->all();
2501+
return (new Collection((new ReflectionClass($instance))->getMethods()))
2502+
->filter(
2503+
fn ($method) => $method->getReturnType() instanceof ReflectionNamedType &&
2504+
$method->getReturnType()->getName() === Attribute::class)
2505+
->map
2506+
->name
2507+
->values()
2508+
->all();
25162509
}
25172510

25182511

0 commit comments

Comments
 (0)