當第三方 class 的 constructor 需要參數時,Laravel 沒辦法自動 resolve,直接 type-hint 注入會報錯。
問題重現
假設有一個第三方的 FakeApi,constructor 需要一個 $token:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| // app/FakeApi.php
namespace App;
class FakeApi
{
private string $token;
public function __construct(string $token)
{
$this->token = $token;
}
public function getToken(): string
{
return $this->token;
}
}
|
在 route 裡直接 type-hint 注入:
1
2
3
4
| // routes/web.php
Route::get('/', static function (FakeApi $api) {
return $api->getToken();
});
|
跑測試會失敗,因為 Container 不知道 $token 要給什麼值:
1
2
3
4
5
6
7
8
9
10
11
| namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_inject_fake_api(): void
{
$this->get('/')->assertOk();
}
}
|
在 ServiceProvider 註冊就好
到 AppServiceProvider 用 bind 告訴 Container 怎麼建立這個 class:
1
2
3
4
5
6
7
8
9
10
11
12
13
| // app/Providers/AppServiceProvider.php
namespace App\Providers;
use App\FakeApi;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind(FakeApi::class, fn() => new FakeApi('foo'));
}
}
|
1
2
3
4
5
6
7
8
9
10
11
| namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_inject_fake_api(): void
{
$this->get('/')->assertOk()->assertSee('foo');
}
}
|
這個做法也讓你不必依賴為 Laravel 特別封裝的 third-party package,升版時少一個卡點。