When Does Dependency Injection Run in Laravel? Before or After Routing?

Does the service container resolve dependencies before the router runs, or only after Laravel knows which controller method to call?

The short answer is:

Laravel resolves controller dependencies after routing, but before the controller method is executed.

Let’s walk through the exact lifecycle.


The Laravel Request Lifecycle (Simplified)

When a request hits your Laravel application, the flow looks like this:

public/index.php

HTTP Kernel

Global Middleware

Router

Container resolves controller

Controller method executed

Response returned

Now let’s zoom in on where Dependency Injection (DI) actually happens.


Step 1: Laravel Boots the Application

At this point:

  • The Service Container is created.
  • Service providers are registered.
  • Bindings and singletons are defined.

Example:

$this->app->bind(UserService::class, function ($app) {
    return new UserService($app->make(UserRepository::class));
});

⚠️ But no controller is instantiated yet.

Laravel has no idea which controller it needs.


Step 2: The Router Determines the Target

Suppose you define a route:

Route::get('/users/{id}', [UserController::class, 'show']);

When a request comes in:

GET /users/5

The router determines:

  • Controller: UserController
  • Method: show
  • Route parameter: id = 5

Only now does Laravel know what needs to be created.


Step 3: The Container Builds the Controller

Once routing is resolved, Laravel asks the container:

“Please create an instance of UserController.”

Example controller:

class UserController
{
    public function __construct(UserService $service)
    {
        $this->service = $service;
    }
}

The container will:

  1. Detect the UserService dependency
  2. Resolve it (and its dependencies)
  3. Inject it into the controller constructor

This is constructor injection.


Step 4: Method Injection Happens

Laravel also supports method injection:

public function show(Request $request, $id)
{
    return $this->service->find($id);
}

Laravel will:

  • Inject the Request object automatically
  • Pass route parameters ($id)
  • Call the method

This happens after the controller is built but before execution.


Why Dependency Injection Cannot Run Before Routing

You might think:

Could Laravel resolve dependencies earlier?

Not for controllers.

Before routing, Laravel doesn’t know:

  • Which controller class to build
  • Which method to call
  • Which dependencies are required

So dependency resolution must wait.


Important: What Is Resolved Before Routing?

Some things are resolved earlier in the lifecycle:

  • The HTTP kernel
  • Global middleware
  • Core services (config, logging, etc.)

But controller-specific dependencies?
Those are resolved only after routing.


What Actually Happens Internally

Under the hood, Laravel roughly does this:

$controller = $container->make(UserController::class);

$response = $controller->show($request, $id);

The magic is in:

$container->make()

That’s where reflection is used to:

  • Inspect constructor parameters
  • Recursively resolve dependencies
  • Instantiate everything automatically

Final Answer

In Laravel:

✔ The Service Container is booted early
✔ The Router determines the controller and method
✔ The Container resolves the controller and its dependencies
✔ Method dependencies are injected
✔ The controller method executes

So dependency injection runs:

After routing, but before the controller method is executed.


Mental Model

Think of it this way:

  • Router decides what to run
  • Container builds what is needed
  • Controller executes business logic