How to implement Dependency Injection in Laravel Livewire
Kirill
Posted on March 26, 2023
I like to use Dependency Injection (DI) in my code. It helps me to keep my code clean and reduces code coupling.
What is Dependency Injection
Dependency Injection is a design pattern that allows for the separation of concerns by removing the responsibility of creating objects and their dependencies from the class that uses them. Instead, these dependencies are provided or injected into the class by a third-party or a container.
Here's an example in PHP:
class UserService {
private $userRepository;
public function __construct(UserRepository $userRepository) {
$this->userRepository = $userRepository;
}
public function getUsers() {
return $this->userRepository->findAll();
}
}
class UserRepository {
public function findAll() {
// fetch users from the database
}
}
In this example, the UserService
requires a UserRepository
object to fetch users from the database. Instead of creating the UserRepository
object inside the UserService
, we inject it via the constructor. This allows for better separation of concerns and makes the UserService
more flexible, as we can easily swap out the UserRepository
implementation without changing the UserService code. You can read more about how it works in Laravel in documentation.
How to use DI with Livewire
When we use Livewire components, we can’t use the __construct
method inside it because Livewire needs $id
for a component.
I started to research and found this thread on GitHub. Some developers recommend using the mount()
method like this:
use Livewire\Component;
use Psr\Log\LoggerInterface;
class Foo extends Component
{
protected LoggerInterface $logger;
public function mount(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function render()
{
$this->logger->info('component rendered');
return view('livewire.foo');
}
public function action()
{
$this->logger->info('action triggered');
}
}
The problem with mount()
DI is that it doesn't work in some cases. For example, when you click on the button and call action()
, your $this->logger
will be empty. This happens because the mount()
method isn't called when the user interacts with the component.
The good news for us is that in version 2.6 of Livewire developers added boot()
hook. This hook will be called every time you use your component. Here's how you can use DI inside your Livewire component:
class YourComponent extends Livewire\Component
{
private SomeService $someService;
private OneMoreService $oneMoreService;
public function boot(
SomeService $someService,
OneMoreService $oneMoreService
)
{
$this->someService = $someService;
$this->oneMoreService = $oneMoreService;
}
}
Posted on March 26, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.