Design Patterns in PHP: Facade (with Laravel)
Tags: php, laravel, designpatterns, facade
Published: 2020-03-03 15:23:19

Design patterns are very important for every developer. it solves very common problems in every project you build.

# Facade pattern definition:

Facade helps you to hide any complex implementation of a class to get an instance of it

# Wikipedia:

a facade is an object that serves as a front-facing interface masking more complex underlying or structural code

# The Problem:

Let's say we have a CMS and with every new post, we want to tweet about it.

First, we will use [dg/twitter-php](https://github.com/dg/twitter-php) library to send tweets. from the README it says the following code should post a tweet

```php
use DG\Twitter\Twitter;

$twitter = new Twitter($consumerKey, $consumerSecret, $accessToken, $accessTokenSecret);

$twitter->send('I am fine today.');
```

Notice here every time we need to get a twitter instance we need to pass some data considered secret. and we don't want to pass them every time we need to send a tweet.

also, we don't need a Factory (Factory Pattern) as we only want to send tweets and using a factory here would be an extra layer of complexity that we don't need.

 
so the Facade pattern can help us hide the complexity of creating an instance by creating this Facade class

```php
class TwitterFacade 
{
  public static function get()
  {
    return new Twitter($consumerKey, $consumerSecret, $accessToken, $accessTokenSecret);
  }
}
```

as we are using laravel. let's put the secrets in `config/services.php`

```php
'twitter' => [
    'api_key' => env('TWITTER_API_KEY'),
    'api_secret' => env('TWITTER_API_SECRET'),
    'api_token' => env('TWITTER_Access_TOKEN'),
    'api_token_secret' => env('TWITTER_Access_TOKEN_SECRET'),
],
```

and then let's update our facade class to use the config like following 

```php
class TwitterFacade 
{
  public static function get()
  {
      $config = config('services.twitter');
      return new Twitter($config['api_key'], $config['api_secret'], $config['api_token'], $config['api_token_secret']);
  }
}
```

and now whenever we want to send tweets we would just write one single line 

```php
TwitterFacade::get()->send('Test tweet from a facade class');
```

# Implement Facade with Laravel

Laravel is supporting the Facade pattern and its part of its core system. if you open `config/app.php` and scroll to the `aliases` you would see a bunch of Facades

```php
'aliases' => [

    'App' => Illuminate\Support\Facades\App::class,
    'Arr' => Illuminate\Support\Arr::class,
    'Artisan' => Illuminate\Support\Facades\Artisan::class,
    'Auth' => Illuminate\Support\Facades\Auth::class,
    'Blade' => Illuminate\Support\Facades\Blade::class,
    'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
    'Bus' => Illuminate\Support\Facades\Bus::class,
    'Cache' => Illuminate\Support\Facades\Cache::class,
    'Config' => Illuminate\Support\Facades\Config::class,
    'Cookie' => Illuminate\Support\Facades\Cookie::class,
    'Crypt' => Illuminate\Support\Facades\Crypt::class,
    'DB' => Illuminate\Support\Facades\DB::class,
    'Eloquent' => Illuminate\Database\Eloquent\Model::class,
    'Event' => Illuminate\Support\Facades\Event::class,
    'File' => Illuminate\Support\Facades\File::class,
    'Gate' => Illuminate\Support\Facades\Gate::class,
    'Hash' => Illuminate\Support\Facades\Hash::class,
    'Lang' => Illuminate\Support\Facades\Lang::class,
    'Log' => Illuminate\Support\Facades\Log::class,
    'Mail' => Illuminate\Support\Facades\Mail::class,
    'Notification' => Illuminate\Support\Facades\Notification::class,
    'Password' => Illuminate\Support\Facades\Password::class,
    'Queue' => Illuminate\Support\Facades\Queue::class,
    'Redirect' => Illuminate\Support\Facades\Redirect::class,
    'Redis' => Illuminate\Support\Facades\Redis::class,
    'Request' => Illuminate\Support\Facades\Request::class,
    'Response' => Illuminate\Support\Facades\Response::class,
    'Route' => Illuminate\Support\Facades\Route::class,
    'Schema' => Illuminate\Support\Facades\Schema::class,
    'Session' => Illuminate\Support\Facades\Session::class,
    'Storage' => Illuminate\Support\Facades\Storage::class,
    'Str' => Illuminate\Support\Str::class,
    'URL' => Illuminate\Support\Facades\URL::class,
    'Validator' => Illuminate\Support\Facades\Validator::class,
    'View' => Illuminate\Support\Facades\View::class,

],
```


Now let's create a new class in `App/Facades/TwitterFacade.php` and put the following content

```php
namespace App\Facades;

use Illuminate\Support\Facades\Facade;

class TwitterFacade extends Facade 
{
    protected static function getFacadeAccessor()
    {
        return 'twitter-poster';
    }
}
```

notice that we are extending `Facade` from `Illuminate` namespace and then we implemented `getFacadeAccessor`. we choose 'twitter-poster' as the name of the Twitter object that we want to use.

Now let's jump to the `AppServiceProvider` to bind the 'twitter-poster' to Twitter. in `AppServiceProvider` at `Register` method add the following

```php
use DG\Twitter\Twitter;

public function register()
{
    $this->app->bind('twitter-poster',function(){
        $config = config('services.twitter');
        return new Twitter($config['api_key'], $config['api_secret'], $config['api_token'], $config['api_token_secret']);
    });
}
```

Now you can see the connection. first, we registered 'twitter-poster' and bind it to an instance of a Twitter class.

The final usage of our facade will be like following

```php
Route::get('/tweet',function(){

    \App\Facades\TwitterFacade::send('Hello from ahmedash.com: Facade design pattern article');

});
```


# Conclusion

We learned what is Facade and what problem does it solve and how to use it with Laravel