@@ -179,6 +179,13 @@ class Container implements ArrayAccess, ContainerContract
179179 */
180180 protected $ afterResolvingAttributeCallbacks = [];
181181
182+ /**
183+ * Whether an abstract class has already had its attributes checked for binding.
184+ *
185+ * @var array<class-string, true>
186+ */
187+ protected $ checkedForBindings = [];
188+
182189 /**
183190 * Define a contextual binding.
184191 *
@@ -962,17 +969,35 @@ protected function getConcrete($abstract)
962969 return $ this ->bindings [$ abstract ]['concrete ' ];
963970 }
964971
972+ if (($ this ->checkedForBindings [$ abstract ] ?? false ) || ! is_string ($ abstract )) {
973+ return $ abstract ;
974+ }
975+
965976 $ attributes = [];
966977 try {
967978 $ attributes = (new ReflectionClass ($ abstract ))->getAttributes (Bind::class);
968979 } catch (ReflectionException ) {
969980 }
970981
982+ $ this ->checkedForBindings [$ abstract ] = true ;
983+
971984 if ($ attributes === []) {
972985 return $ abstract ;
973986 }
974987
975- $ this ->bind ($ abstract , $ attributes [0 ]->newInstance ()->concrete );
988+ return $ this ->getConcreteBindingFromAttributes ($ abstract , $ attributes );
989+ }
990+
991+ /**
992+ * Get the concrete binding for an abstract from the Bind attribute.
993+ *
994+ * @param string $abstract
995+ * @param array<int, \ReflectionAttribute<Bind>> $reflectedAttributes
996+ * @return mixed
997+ */
998+ protected function getConcreteBindingFromAttributes ($ abstract , $ reflectedAttributes )
999+ {
1000+ $ this ->bind ($ abstract , $ reflectedAttributes [0 ]->newInstance ()->concrete );
9761001
9771002 return $ this ->bindings [$ abstract ]['concrete ' ];
9781003 }
@@ -1647,6 +1672,7 @@ public function flush()
16471672 $ this ->instances = [];
16481673 $ this ->abstractAliases = [];
16491674 $ this ->scopedInstances = [];
1675+ $ this ->checkedForBindings = [];
16501676 }
16511677
16521678 /**
0 commit comments