How To Bind An Interface To An Implementation In Laravel

Binding an interface to an implementation promotes good coding practices. As a result the code is less coupled, more maintainable, and testable.

Why might someone want to bind an interface using Laravel? To put an abstraction between the application and the concretion. A concretion is a class that implements the interface. It is a specific implementation, in our example it will be Amazon S3 file storage provider. The application doesn’t care which implementation it receives just that it receives an implementation with the guaranteed functions.

Lets build functionality to interact with files on a storage provider such as Amazon S3. Initially all files will be uploaded and deleted on S3 only. There are other ways to accomplish this and the main goal is to demonstrate how to bind an interface to an implementation and not so much the actual code to upload to a storage provider.

Create An Interface

The interface will determine which functions are available on the concrete implementation through the binding.

Create The Concrete Implementation

The concretion is an Amazon S3 file storage provider. This file is where Amazon specific upload/delete functionality goes.

Create The Laravel Service Provider

The Laravel service provider is the mechanism that binds the FileStorageInterface to the S3FileStorage class implementation. This means if we use dependency injection for the FileStorageInterface or use App:make it will automatically resolve to the S3FileStorage class.

Using The Interface

In the below example we are not using the implementation directly. Instead it is automatically resolved through the service provider which returns the concrete implementation. Laravel will automatically resolve dependencies if they are in the __construct() functions. We can see below that the controller doesn’t know about Amazon and nor should it. I am only using the controller in this example to provide a demonstration. There are other places where we would use the storage provider that might better organize the code.

Final Thoughts

If we wanted to swap out for Dropbox or some other provider the impact is minimal, create a Dropbox implementation and change the provider. The application would now use the Dropbox implementation instead of the Amazon S3 implementation.

Following this pattern can also help separate the application from Laravel which could make reusing this code in other projects easier than if the Amazon S3 code were included in a model directly. Definitely think about how to best structure your code and not to fall into the framework convenience trap of putting everything in a model, controller or view. In most cases there are better places for code than those 3 areas.

Share this Story
Load More Related Articles
Load More By Nick Escobedo
Load More In Laravel
  • MKJ

    Awesome post! Thanks for sharing.

  • ben sholdice

    is this a typo: “Why might someone want to bind and interface using Laravel” – did you mean ‘..bind an interface..’?

    is this a typo: “The Laravel service provider is the mechanism that binds the FilterStorageInterface to the S3FileStorage class implementation” – did you mean ‘..binds the FileStorageInterface to the …’ ?

    • Thank you, the post has been updated. Not sure if you saw my reply on the other post you commented on, but I really appreciate that you have left comments.

  • JP

    I am using your code but unfortunately it is not working. See below

    Below is my Interface

    namespace Appcustom;

    interface Jininterface
    {
    public function a();
    public function b();
    }

    Below is my Class

    namespace Appcustom;

    class Jinaal implements Jininterface
    {
    public function a()
    {
    return ‘From A…’;
    }
    public function b()
    {
    return ‘From B…’;
    }
    }

    Below is my binding within AppServiceContainer

    public function register()
    {
    $this->app->bind(‘Jininterface’, ‘AppcustomJinaal’);
    }

    Now i am injecting Jininterface to my controllers’s constructor

    namespace AppHttpControllers;
    use IlluminateHttpRequest;

    class TestController extends Controller
    {
    protected $j;
    public function __construct(Jininterface $j)
    {
    $this->j=$j;
    }

    public function bab()
    {
    echo $this->j->a().””;
    echo $this->j->b().””;
    }
    }

    But it is giving me below error.

    Class AppHttpControllersJininterface does not exist.

    Please help to resolve this.

    • In your controller make sure to add a use statement for your Jinterface. If you don’t put a namespace on a class it will try to automatically resolve from the same namespace that you are trying to use the class from. So in this case it’s trying to import Jinterface from the Controllers namespace.

      Let me know if that helps.

Check Also

Trade-offs

As developers we work with non-technical people and ...