PHPnews.io

Response: Don’t Use Facades

Written by Taylor Otwell / Original link on Jan. 13, 2014

This afternoon an article was posted to Reddit that cautioned users of Laravel to stop using “Facades”.

In the context of Laravel, Facades are what you are using when you make what appears to be a static call to a class. For example:

Route::get('/', 'HomeController@showWelcome');

However, as many of you are already aware, this call may be rewritten like so:

$app['router']->get('/', 'HomeController@showWelcome');

The code may be written easier way because, at their core, facades are syntactic sugar for service location. When you make a call to a Facade, the Facade resolves the underlying class out of the Laravel IoC container and calls the intended method on the instance. They provide a very terse, expressive syntax, while still maintaining the ability to test your code.

However, service location can lead developers into some bad architectural habits. For instance, since service location is very “easy”, it can lead to responsibility bloat in your classes. Generally, classes with small, focused responsibilities are to be desired since they are easier to understand, test, debug, etc. However, if you are using Facades to push to the queue, send an e-mail, and validate some data all within a single class, that class’ core responsibilities are obscured. It is concerned about way too many things.

It is possible to use Facades responsibly and keep your class responsibilities narrowly focused. However, some prefer the discipline that constructor injection provides. Constructor injection means that a class’ dependencies are injected via the constructor when that class is created. It is an explicit declaration of what that class needs, and therefore gives an idea as to what that class does.

Before today, injecting the underlying class behind a facade required some explicit bindings to be registered in the IoC container; however, starting today, it is now just as easy to inject your dependencies as it is to use a Facade. By simply type-hinting the class underlying the Facade, it will automatically be injected by the container when it is needed as a dependency.

For example, need an instance of the Session injected into a controller? Just do this:

<?php

class HomeController extends BaseController {

	public function __construct(Illuminate\Session\Store $session)
	{
		$this->session = $session;
	}

}

There is no longer any need to do any extra configuration. Since all controllers are automatically resolved by the Laravel IoC container, the session instance will automatically be injected. Injecting the class underlying the Facade is just as easy as using the Facade itself! If you love using Facades, keep on using them, just keep an eye on those class responsibilities! If you prefer constructor injection, it just got a heck of a lot easier!

If you’re not sure what class to type-hint, check out the Facade To Class Reference from the Laravel documentation.

Enjoy!

taylorotwell 15

« Full IoC & Unit Testing With Laravel - Unifying PHP »