Contextual binding in laravel and how to make your code meet O in SOLID principles

Sometimes, we meet these kind of use cases or features when doing web application programming:

1 – multiple type of report to generate

2-  multiple type of discount to handle

3- multiple type of payment to handle

I recently faced with this use case when doing a freelance project for my customer.

The requirement for this use case is that we have 2 types of reporting: human resources reporting and accounting reporting. And, for quick and dirty we have simple solution for this as below (we use laravel framework 5)

In routes.php, I added this line

type can be: hr or accounting

and the ReportController controller file, in this file based on type of $type variable, we will call the correspond function.

and we simple have the ReportRepository

now, try php artsian serve, and go to localhost:

http://localhost:8000/report/hr or http://localhost:8000/report/accounting

accounting report
accounting report

The idea for this simple solution is that:

  • In ReportController.php, I injected ReportRepository class into
  • For each type of report (report/accounting or report/hr), the instance $report (type of ReportRepository) will call correspond function with the type of report.

The problem with this way is that it violated Open for extension and close for modification (O) rule in SOLID principle ( I have an article about SOLID principle here ) . For e.g: In case, you have another type of report, you must go to the controller and add more if condition, and add more code for the new report type in ReportRepository as well.

By following the O in SOLID principle, you can reduce if condition, separating the of concern of type of report into another class (in this case, I used laravel fw – so the class file is ApplicationServiceProvider), decoupling code dependency and easy for testing (mocking the interface is alway easy).

So, let’s implement new way that follow O in SOLID principle.

The idea for this way is:

  • For each type of report, there will be an implementation of function show of ReportRepositoryInteface interface.
  • Injecting ReportRepositoryInteface into each controller for each type of report
  • Binding based context ( type of report) in AppServiceProvider class

I hope it much easier for you to understand the second implementation with this diagram ( not actually class diagram)

class diagram for example use case
class diagram for example use case

First, we need ReportRepositoryInterface.php file

then, AccountingReportRepository.php

and HrReportRepository.php

Then, how to make those code work in laravel framework, yah, laravel >5 support contextual binding here

adding 2 lines into the routes.php file

It is more reasonable to consider report is an action in AccountingController or HrController ?? 🙂



Then, you just need to bind the concrete class to abstract class just in contextual. The logic is as it is:

  • when AccountingController need ReportRepositoryInterface give it AccountReportRepository
  • when HrController need ReportRepositoryInterface give it HrReportRepository

and, just need to add the code in register function of AppServiceProvider (github code)

github code for this tutorial (it may contain code of another tutorial):


@todo: write a demo test code for the repository

Release optivo mail client for laravel

Optivo is quite big mail service provider in Germany
This is one of optivo mail client for laravel (use Optivo HTTP API)

write an article about how to create your own laravel package like this package