thr01092025
thr01092025

Reputation: 1

Nested run time dependency injection using Laravel Service Container

I understand how to use the Laravel Service Container bind() method to bind static dependencies, even if it's nested:

$this->app->bind(Interface::class, function () {
    return new Implementation(new ImplementationDependency());
});

So if I have another class that would utilize this dependency, Laravel would just resolve Interface::class from the container without any issues:

class UtilizingClass {
   public function __construct(
       Interface $resolvedImplementation,
       Interface2 $anotherdependency, // Also resolved in container
       Interface3 $yetAnotherDependency, // Also resolved in container
   ) { ... }
}

UtilizingClass instantiation:

$service = app(UtilizingClass::class);

But how do I do it when ImplementationDependency() relies on a run-time dependency and I still need to inject it to the method?

Assuming this is the code:

class ImplementationDependency
{
    public function __construct(\App\Models\User $user) {}
    ...
}

How can I pass the user on run-time?

This is what I've tried:

$this->app->bind(Interface::class, function ($app, $params) {
    return new Implementation(new ImplementationDependency($params['user']));
});

The controller method above will no longer work because it doesn't have a default argument for the \App\Models\User class:

$service = app(UtilizingClass::class); // Error, doesn't know how to resolve user params.

Is the only way to do this like this?

$service = new UtilizingClass(
app(Interface::class, ['user' => $user]),
app(Interface2::class),
app(Interface3::class),
);

Upvotes: 0

Views: 23

Answers (1)

Motunrayo Koyejo
Motunrayo Koyejo

Reputation: 397

Laravel provides the app()->make() method, which allows you to pass runtime parameters. link to docs here: https://laravel.com/docs/11.x/container#the-make-method

Upvotes: 0

Related Questions