diff --git a/src/Illuminate/Container/Container.php b/src/Illuminate/Container/Container.php index 58f5b89e064e..8c31eb26c103 100755 --- a/src/Illuminate/Container/Container.php +++ b/src/Illuminate/Container/Container.php @@ -836,7 +836,9 @@ protected function resolve($abstract, $parameters = [], $raiseEvents = true) // Before returning, we will also set the resolved flag to "true" and pop off // the parameter overrides for this build. After those two things are done // we will be ready to return back the fully constructed class instance. - $this->resolved[$abstract] = true; + if (! $needsContextualBuild) { + $this->resolved[$abstract] = true; + } array_pop($this->with); diff --git a/tests/Container/ContainerExtendTest.php b/tests/Container/ContainerExtendTest.php index a34c5c6ef9d6..0f89a54fd902 100644 --- a/tests/Container/ContainerExtendTest.php +++ b/tests/Container/ContainerExtendTest.php @@ -187,6 +187,43 @@ public function testUnsetExtend() $this->assertSame('foo', $container->make('foo')); } + + public function testExtendContextualBinding() + { + $container = new Container(); + $container->when(ContainerExtendConsumesInterfaceStub::class) + ->needs(ContainerExtendInterfaceStub::class) + ->give(fn () => new ContainerExtendInterfaceImplementationStub('foo')); + + $container->extend(ContainerExtendInterfaceStub::class, function ($instance) { + self::assertInstanceOf(ContainerExtendInterfaceImplementationStub::class, $instance); + self::assertSame('foo', $instance->value); + + return new ContainerExtendInterfaceImplementationStub('bar'); + }); + + self::assertSame('bar', $container->make(ContainerExtendConsumesInterfaceStub::class)->stub->value); + } + + // https://github.com/laravel/framework/issues/53501 + public function testExtendContextualBindingAfterResolution() + { + $container = new Container(); + $container->when(ContainerExtendConsumesInterfaceStub::class) + ->needs(ContainerExtendInterfaceStub::class) + ->give(fn () => new ContainerExtendInterfaceImplementationStub('foo')); + + $container->make(ContainerExtendConsumesInterfaceStub::class); + + $container->extend(ContainerExtendInterfaceStub::class, function ($instance) { + self::assertInstanceOf(ContainerExtendInterfaceImplementationStub::class, $instance); + self::assertSame('foo', $instance->value); + + return new ContainerExtendInterfaceImplementationStub('bar'); + }); + + self::assertSame('bar', $container->make(ContainerExtendConsumesInterfaceStub::class)->stub->value); + } } class ContainerLazyExtendStub @@ -198,3 +235,23 @@ public function init() static::$initialized = true; } } + +interface ContainerExtendInterfaceStub +{ +} + +class ContainerExtendInterfaceImplementationStub implements ContainerExtendInterfaceStub +{ + public function __construct( + public string $value, + ) { + } +} + +class ContainerExtendConsumesInterfaceStub +{ + public function __construct( + public ContainerExtendInterfaceStub $stub, + ) { + } +}