@@ -130,6 +130,13 @@ class Container implements ArrayAccess, ContainerContract
130
130
*/
131
131
protected $ checkedForAttributeBindings = [];
132
132
133
+ /**
134
+ * Whether a class has already been checked for Singleton or Scoped attributes.
135
+ *
136
+ * @var array<class-string, "scoped"|"singleton"|null>
137
+ */
138
+ protected $ checkedForSingletonOrScopedAttributes = [];
139
+
133
140
/**
134
141
* All of the registered rebound callbacks.
135
142
*
@@ -281,7 +288,7 @@ public function isShared($abstract)
281
288
return false ;
282
289
}
283
290
284
- if (($ scopedType = $ this ->getScopedTyped (new ReflectionClass ( $ abstract) )) === null ) {
291
+ if (($ scopedType = $ this ->getScopedTyped ($ abstract )) === null ) {
285
292
return false ;
286
293
}
287
294
@@ -297,20 +304,36 @@ public function isShared($abstract)
297
304
/**
298
305
* Determine if a ReflectionClass has scoping attributes applied.
299
306
*
300
- * @param ReflectionClass<object> $reflection
307
+ * @param ReflectionClass<object>|class-string $reflection
301
308
* @return "singleton"|"scoped"|null
302
309
*/
303
- protected function getScopedTyped (ReflectionClass $ reflection ): ?string
310
+ protected function getScopedTyped (ReflectionClass | string $ reflection ): ?string
304
311
{
305
- if (! empty ($ reflection ->getAttributes (Singleton::class))) {
306
- return 'singleton ' ;
312
+ $ className = $ reflection instanceof ReflectionClass
313
+ ? $ reflection ->getName ()
314
+ : $ reflection ;
315
+
316
+ if (array_key_exists ($ className , $ this ->checkedForSingletonOrScopedAttributes )) {
317
+ return $ this ->checkedForSingletonOrScopedAttributes [$ className ];
307
318
}
308
319
309
- if (! empty ($ reflection ->getAttributes (Scoped::class))) {
310
- return 'scoped ' ;
320
+ try {
321
+ $ reflection = $ reflection instanceof ReflectionClass
322
+ ? $ reflection
323
+ : new ReflectionClass ($ reflection );
324
+ } catch (ReflectionException ) {
325
+ return $ this ->checkedForSingletonOrScopedAttributes [$ className ] = null ;
326
+ }
327
+
328
+ $ type = null ;
329
+
330
+ if (! empty ($ reflection ->getAttributes (Singleton::class))) {
331
+ $ type = 'singleton ' ;
332
+ } elseif (! empty ($ reflection ->getAttributes (Scoped::class))) {
333
+ $ type = 'scoped ' ;
311
334
}
312
335
313
- return null ;
336
+ return $ this -> checkedForSingletonOrScopedAttributes [ $ className ] = $ type ;
314
337
}
315
338
316
339
/**
@@ -1753,6 +1776,7 @@ public function flush()
1753
1776
$ this ->abstractAliases = [];
1754
1777
$ this ->scopedInstances = [];
1755
1778
$ this ->checkedForAttributeBindings = [];
1779
+ $ this ->checkedForSingletonOrScopedAttributes = [];
1756
1780
}
1757
1781
1758
1782
/**
0 commit comments