Writing a Laravel Facade With a Service Provider

Prior to me discovering how the Laravel internals work, I would define static methods for most of my services. It quickly gets difficult to manage, once you need to keep non static state for a service, or you want dynamic behavior that is determined at runtime. In this post I’ll share how I defined my own Asset class facade that is registered to the Laravel container in a service provider. First, let’s take a minute to understand my original Asset class. It was your typical static class.

The motivation for creating a custom Asset class was to be able to call it from a view. Amezmo has an asset build pipeline that generates a 16 byte hash of the filename. This hash is then stored to be used as a URI segment for cache busting JavaScript and CSS files.

The problem with the static asset class however, is that you cannot use Laravel’s DI container to inject services, such as a configuration block, or anything else that you would need. So, for the new non static implementation. I started off by following Laravel’s pattern of putting each provider in it’s own directory. Create a new directory under your app directory called Asset. I added AssetManagerInterface to best follow the SOLID principles. However, it isn’t necessary to always implement an interface for a simple service .


Implementing the Service Provider

The Laravel DI container is powerful. It’s especially useful for registering singelton classes, such as the Asset class or a connection Redis, for example. Lot’s of Laravel’s built-in providers are singeltons.

It’s worth noting that you do not have to register your services directly. Laravel is smart enough to construct an instance of your service. However, since I am passing in a non-reference type as the first argument, Laravel would not be able to, simply because primitive values have no context. Once we have the service provider register to the container, we’re ready to add it to our app/config/app.php configuration array

The entry added to the aliases array is that the facade Asset can be invoked from a view. Now let’s take a look at AssetManager where the real logic, hiding behind the facade actually takes place I’ve added other methods in this class. Perhaps it might give you some inspiration in your own projects.

As you can see, the constructor defines it’s dependencies and we provide them in the AssetServiceProvider This is great for performance, because we will be able to store the configuration in memory, and not, for example, call env() many times, which may end up calling into getenv from the C standard library.

The Asset facade is very simple. It defines one method called getFacadeAccessor with returns a string with the value we’ve returned from AssetServiceProvider::provides()

Benefits of Service Provider pattern with Facades

  • Being able to mock your service properly
  • Not depending on any hard coded dependencies.
  • All your dependencies are defined in your constructor, so you can swap in specific implementations for your use specific use case. For example, if you need different behavior for the service in a production or development environment.

This blog is hosted by Amezmo. Amezmo makes zero-downtime deployment for PHP easy.