Featured image of post Use Laravel Container bind to Inject Any Third-Party Package

Use Laravel Container bind to Inject Any Third-Party Package

When a third-party class needs constructor parameters, Laravel cannot auto-resolve it. Register it with bind in a ServiceProvider to enable type-hint injection.

When a third-party class requires constructor parameters, Laravel’s container can’t auto-resolve it. Directly type-hinting it for injection will throw an error.

Reproducing the Problem

Suppose there’s a third-party FakeApi whose constructor requires a $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;
    }
}

Type-hinting it directly in a route:

1
2
3
4
// routes/web.php
Route::get('/', static function (FakeApi $api) {
    return $api->getToken();
});

The test will fail because the container doesn’t know what value to pass for $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();
    }
}

Register It in a ServiceProvider

In AppServiceProvider, use bind to tell the container how to create the 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');
    }
}

This also removes the dependency on Laravel-specific wrapper packages, which means one fewer thing to worry about during version upgrades.