4242use ReflectionNamedType ;
4343use RuntimeException ;
4444use Stringable ;
45+ use Throwable ;
4546use ValueError ;
4647
4748use 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