Do you know what are service providers and how they work on Laravel?
In this Article we'll provide a real world example creating an interface and using a service provider to bind it to an implementation.
What is a service provider in Laravel?
According to Laravel's docs:
Service providers are the central place of all Laravel application bootstrapping. Your own application, as well as all of Laravel's core services, are bootstrapped via service providers.
That means all core services on Laravel (Middlewares, Routes, Mailers, queues, etc) are "bootstraped" via service providers.
If you want to learn more about how service providers work, check out Laravel docs, in this tutorial we'll focus on using service providers and interfaces to implement dependency injection, and the adapter pattern.
Real-world example: Interface
So, let's supose you want to create a User Repository class, but you are not sure if you will change your project's ORM in the future.
That's the perfect scenario to use an interface + adapter pattern, right? This way you only create a UserRepository
Interface and you can have multiple implementations like EloquentUserRepository
, DoctrineUserRepository
, PDOUserRepository
, etc.
So our Interface would be like this:
interface UserRepository
{
public function add(UserFormRequest $request): Users;
}
But when you inject the interface on the controller or service layer how do you bind the implementation you want to use to the interface?
Injecting the interface on the controller/service layer:
So, now we have a User controller that receives the UserRepository via Dependency injection, it looks like this:
class UserController extends Controller
{
public function __construct(private UserRepository $repository)
{
// Dependency injection
}
public function store(UsersFormRequest $request)
{
$serie = $this->repository->add($request);
}
}
How our application knows that we want specific EloquentUserRepository
instead DoctrineUserRepository
for example? That's how service provider work their magic.
Binding the interface to the chosen implementation
First, we'll create our service provider using the artisan command: php artisan make:provider UserRepositoryProvider
. Now we have a new provider on app\Providers\UserRepositoryProvider.php
.
class UserRepositoryProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
$this->app->bind(\App\Repositories\UserRepository::class, \App\Repositories\EloquentUserRepository::class);
}
}
The register()
method will take charge to bind our interface to the chosen implementation (EloquentUserRepository), so in the future, if we want to change this implementation to Doctrine for example, we just need to change on our service provider!
App Config
Lastly, we need to add this provider to our Laravel's app.php
config file, so it knows what to do. in app\config\app.php
on providers array you will add this line:
App\Providers\UserRepositoryProvider::class,
And that's it! Now you have an interface binded to a real implementation using service providers. That's one use of case to this great feature of laravel, but you can explore more on Laravel docs to discover more possibilities.
Thanks for reading!
Top comments (0)