From 1279732789980b444d06b39851a3388b37282afb Mon Sep 17 00:00:00 2001 From: Choraimy Kroonstuiver <3661474+axlon@users.noreply.github.com> Date: Thu, 14 Nov 2024 10:34:16 +0100 Subject: [PATCH] Fix extensions of contextual bindings --- src/Illuminate/Container/Container.php | 4 +- tests/Container/ContainerExtendTest.php | 57 +++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) 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, + ) { + } +}