Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Container::extend() breaks when $abstract was previously contextually bound #53501

Closed
axlon opened this issue Nov 13, 2024 · 0 comments · Fixed by #53514
Closed

Container::extend() breaks when $abstract was previously contextually bound #53501

axlon opened this issue Nov 13, 2024 · 0 comments · Fixed by #53514

Comments

@axlon
Copy link
Contributor

axlon commented Nov 13, 2024

Laravel Version

11.31.0

PHP Version

8.3.10

Database Driver & Version

n/a

Description

Its possible to use Container::extend() to extend the behavior of a container service, this makes it easy to compose behavior based on specific needs. However when using this feature together with contextual bindings it may fail depending on a few factors (detailed below).

Steps To Reproduce

  1. Register a contextual binding in the container, this binding must resolve something that the container can't build on its own (e.g. an interface)
  2. Trigger the contextual binding
  3. Register an extension for the $abstract (e.g. the interface) that we bound contextually in the prior step

If you followed steps 1, 2, and 3 an exception will be thrown, as whatever interface you picked cannot be resolved. If you skip step 2, everything works as expected.

Below is some example code that contains both scenarios:

<?php

namespace LaravelContainerBugExample;

use Illuminate\Container\Container;

require_once __DIR__ . '/vendor/autoload.php';

interface Foo
{
}

class Bar implements Foo
{
}

class Baz
{
    public function __construct(
        public Foo $foo,
    ) {
    }
}

class Qux implements Foo
{
    public function __construct(
        private Foo $foo,
    ) {
    }
}

$container = new Container();
$container->when(Baz::class)->needs(Foo::class)->give(fn () => new Bar());

// This works...
$app = clone $container;
$app->extend(Foo::class, fn (Foo $foo) => new Qux($foo));

$baz = $app->make(Baz::class);
echo $baz->foo instanceof Qux ? 'Foo implementation was extended' : 'Foo implementation was not extended';
echo PHP_EOL;

// This breaks...
$app = clone $container;
$app->make(Baz::class);
$app->extend(Foo::class, fn (Foo $foo) => new Qux($foo));
@axlon axlon changed the title [11.x] Container::extend() breaks when $abstract was previously contextually bound Container::extend() breaks when $abstract was previously contextually bound Nov 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant