Troubleshooting

Common issues when using wpzylos-container.

Resolution Issues

EntryNotFoundException

Problem: EntryNotFoundException: No entry found for "MyService"

Cause: Service not registered in container.

Fix: Bind the service before resolving:

// Register first
$container->bind(MyService::class);

// Then resolve
$service = $container->get(MyService::class);

BindingResolutionException

Problem: BindingResolutionException: Unable to resolve dependency

Cause: Auto-wiring failed due to unresolvable dependency.

Fix: Check constructor parameters:

class MyService
{
    // Bad: Can't auto-wire primitive without binding
    public function __construct(string $apiKey) {}

    // Good: Can auto-wire class dependencies
    public function __construct(Logger $logger) {}
}

// For primitives, bind explicitly:
$container->bind(MyService::class, fn() => new MyService('my-key'));

Circular Dependency

Problem: Container hangs or stack overflow.

Cause: Class A needs B, class B needs A.

Fix: Break cycle with setter injection:

// Bad: Circular
class A { public function __construct(B $b) {} }
class B { public function __construct(A $a) {} }

// Good: Break with setter
class B {
    private ?A $a = null;
    public function setA(A $a): void { $this->a = $a; }
}

$container->singleton(A::class);
$container->singleton(B::class, function ($c) {
    $b = new B();
    $b->setA($c->get(A::class));
    return $b;
});

Binding Issues

Singleton returns different instances

Problem: singleton() binding returns new instance each call.

Cause: Binding overwritten or wrong method used.

Fix: Verify you're using singleton() not bind():

// Bad: Creates new instance each time
$container->bind(Database::class);

// Good: Same instance every time
$container->singleton(Database::class);

Interface binding not resolving

Problem: get(Interface::class) fails even after binding.

Cause: Binding uses wrong interface name or namespace.

Fix: Use fully qualified class names:

// Bad: Missing namespace
$container->bind('LoggerInterface', FileLogger::class);

// Good: Full namespace
$container->bind(
    \Psr\Log\LoggerInterface::class,
    \App\Logging\FileLogger::class
);

Auto-wiring Issues

Optional parameters not working

Problem: Optional constructor parameter causes resolution failure.

Cause: Parameter type can't be resolved and has no default.

Fix: Ensure optional parameters have defaults:

class Service
{
    // Bad: No default, will fail if Cache not bound
    public function __construct(?CacheInterface $cache) {}

    // Good: Has default, will use null if not bound
    public function __construct(?CacheInterface $cache = null) {}
}

Union types failing

Problem: A|B union type parameter fails to resolve.

Cause: Container doesn't know which type to use.

Fix: Bind explicitly or use first resolvable type:

// Bind the specific type you want
$container->bind(LoggerInterface::class, FileLogger::class);

PSR-11 Compatibility

Third-party library rejects container

Problem: Library throws Container must implement ContainerInterface.

Cause: Import mismatch or interface not implemented.

Fix: Verify container implements PSR-11:

use Psr\Container\ContainerInterface;

$container = new Container();
assert($container instanceof ContainerInterface); // Should pass