Supercharge Your Laravel Application with Service Providers

Opadaalziede
4 min readJul 9, 2023

In Laravel, Service Providers are a powerful tool for organizing and registering your application’s services. Service Providers allow you to register bindings and other objects with Laravel’s service container, which can then be injected into your application’s classes and controllers.

In addition to explaining how to use Service Providers, I will strive to ensure that the code is highly reusable by adhering to SOLID design principles and patterns.

The idea is that we will implement a simple notification functionality that allows us to notify our users about a certain message. We will be able to notify our users through the application (database level notifications) or via SMS.

So, we will start by defining a NotificationInterface,and within this interface we are going to define a method callednotifyaccepts a list of users and a message parameter.

Notification Interface

Next, we will implement two different implementations of this interface.

But before that, there is another interface we should define, which is the NotifiableInterface, and implement this interface in our User model.

Notifiable Interface

By using this interface we can ensure that classes that need to receive notifications implement the required methods, notifyViaApplication and notifyViaSms. This makes it easier to send notifications to a group of objects without worrying about their specific implementation details, such as which notification channels they support.

Here, we can implement another SOLID design pattern called Interface Segregation. We can split our NotifiableInterface into two interfaces (ApplicationNotifiableInterface and SmsNotifiableInterface) using this pattern. By doing so, we can let our classes decide which notification mechanism they support without the need to provide implementation to methods they don't need. However, we will keep things simple here and use one interface with two methods.

Moving to our NotificationInterface implementations:

  1. DatabaseNotification implementation: This class will be responsible for notifying users via the application.
Database notification implementation

Nothing too fancy here, we loop through our users and call the notifyViaApplication method on each one.

The notifyViaApplication method can be implemented in various ways, but this is beyond the scope of our topic for today.

2- SmsNotification implementation: this class will be responsible for notifying users via SMS.

Sms notification implementation

This abstraction allows us to switch our notification implementation easily.

We can call notifyViaApplication and notifyViaSms on our User model here because it implements the NotifiableInterface that we discussed earlier.

Now, Let’s implement our ApplicationNotificationController:

Application Notification Controller

In this code, we’re injecting both a NotificationInterface implementation and a UserRepositoryInterface implementation into our controller. This approach ensures that our controller is completely unaware of where our user data is coming from. Additionally, the UserRepositoryInterface and its implementations can be implemented in the same way as theNotificationInterface.

SmsNotificationController:

The same thing happens here, we’re injecting both aNotificationInterface implementation and a UserRepositoryInterface implementation into our controller.

The last thing we need to do is to register our bindings in the container, and to do that we will implement a custom Service Provider. Let’s call it NotificationServiceProvider.

The registration logic should be in the register method.

Here we are telling the service container that whenever an implementation of the NotificationInterfaceis requested by our ApplicationNotificationController, it should provide an instance of the DatabaseNotificationclass.

And whenever an implementation of the NotificationInterfaceis requested by our SmsNotificationController, it should provide an instance of the SmsNotificationclass.

This type of binding is called Contextual Binding.

After defining our service provider, we need to register it with our application. To do this, we can add it to the providers array in the config/app.php file:

Registering our service provider

Now Laravel will automatically load our service provider and call its register method during the bootstrapping phase of the application.

Conclusion:

The code demonstrates how to use service providers and dependency injection in Laravel to build a flexible and scalable architecture. It separates the notification logic from the rest of the application and defines a clear interface for all notification implementations, making it easy to add new notification methods in the future. The use of dependency injection and service providers also makes it easy to swap out different implementations of the NotificationInterface and UserRepositoryInterface without having to modify the controller.

Overall, this code provides a solid foundation for building a notification system in Laravel that is maintainable, testable, and extensible.

--

--