It doesn't. You have to explicitly call App::make()
to create an instance. The same goes for calling other methods using App:call()
.
Here's the relevant section of the docs: https://laravel.com/docs/10.x/container#the-make-method
UPD
Assume the following controller:
<?php
namespace App\Http\Controllers;
use App\Models\Order;
use App\Services\OrderService;
class OrderController extends Controller
{
protected OrderService $service;
public function __construct(OrderService $service) {
$this->service = $service;
}
public function update(Order $order)
{
return $this->service->update($order);
}
}
The contents of OrderService:
<?php
namespace App\Services;
use App\Models\Order;
class OrderService {
public function __construct(bool $dry) { /* */ }
public function update(Order $order) { /* */ }
}
In your service provider you have:
$this->app->when(OrderService::class)->needs('$dry')->give(false);
And in your routes/api.php
Route::get('/order/{order}', [OrderController::class, 'update']);
Now what happens when make a request to api/order/1
? First, the OrderController
instance is created. You provided the class name when registering the route, so Laravel knows which class to use. The instances is created with a call of make
. As you mention in the quetion, reflections are used to determine, what arguments are expected by the constructor. In our case it's just the instance of OrderService
.
So now Laravel will try to resolve this dependency. It's a class, not an interface, so Laravel will simply try to create it's instance, again using make
. Again, analysing the constructor it will determine that it needs boolean parameter $dry
. For which we have registered a resolver in our service provider.
So $dry
gets passed to the OrderService
constructor, Laravel gets an instance and passes it to OrderController
constructor. Now it can call the update
method.
By the same logic, the call
method is used to resolve all dependencies. In this case it's just model dependency, which Laravel can resolve out of the box.
The general idea here is that make
and call
are always being called somewhere under the hood. There's no mechanism to intercept a native call to constructor or method. For example, if you modify routes/api.php
like this:
Route::get('/order/{order}', function($order) {
$controller = new OrderController();
return $controller->update($order);
});
You'll get an ArgumentCountError for the constructor call.