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:
- Detect the
UserServicedependency - Resolve it (and its dependencies)
- 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
Requestobject 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
