@@ -133,6 +133,13 @@ class Container implements ArrayAccess, ContainerContract
133133 */
134134 protected $ afterResolvingCallbacks = [];
135135
136+ /**
137+ * All the abstract keys which are bound with class names.
138+ *
139+ * @var array
140+ */
141+ protected $ boundToClassName = [];
142+
136143 /**
137144 * Define a contextual binding.
138145 *
@@ -222,6 +229,7 @@ public function isAlias($name)
222229 public function bind ($ abstract , $ concrete = null , $ shared = false )
223230 {
224231 $ this ->dropStaleInstances ($ abstract );
232+ $ this ->decideAboutConcreteType ($ abstract , $ concrete );
225233
226234 // If no concrete type was given, we will simply set the concrete type to the
227235 // abstract type. After that, the concrete type to be registered as shared
@@ -674,7 +682,11 @@ protected function resolve($abstract, $parameters = [])
674682 $ this ->instances [$ abstract ] = $ object ;
675683 }
676684
677- $ this ->fireResolvingCallbacks ($ abstract , $ object );
685+ // We don't fire "resolving" callbacks for interface bound with class path syntax
686+ // since the callback will fire later, when the bounded concrete is resolving.
687+ if (! $ this ->isAnInterfaceBoundedWithClassName ($ abstract )) {
688+ $ this ->fireResolvingCallbacks ($ abstract , $ object );
689+ }
678690
679691 // Before returning, we will also set the resolved flag to "true" and pop off
680692 // the parameter overrides for this build. After those two things are done
@@ -1269,4 +1281,31 @@ public function __set($key, $value)
12691281 {
12701282 $ this [$ key ] = $ value ;
12711283 }
1284+
1285+ /**
1286+ * Determine if the abstract is both an interface and is bounded to a class path (not a closure).
1287+ *
1288+ * @param string $abstract
1289+ * @return bool
1290+ */
1291+ protected function isAnInterfaceBoundedWithClassName ($ abstract )
1292+ {
1293+ return interface_exists ($ abstract ) && array_key_exists ($ abstract , $ this ->boundToClassName );
1294+ }
1295+
1296+ /**
1297+ * Detects what type of concrete is provided for the abstract.
1298+ *
1299+ * @param string $abstract
1300+ * @param \Closure|string|null $concrete
1301+ * @return void
1302+ */
1303+ protected function decideAboutConcreteType ($ abstract , $ concrete )
1304+ {
1305+ if ($ concrete instanceof Closure) {
1306+ unset($ this ->boundToClassName [$ abstract ]);
1307+ } else {
1308+ $ this ->boundToClassName [$ abstract ] = null ;
1309+ }
1310+ }
12721311}
0 commit comments