Laravelファサードの作り方からその構造まで徹底解説入門

Laravelの特徴の一つといえば、、ファサード!

と言われるほど、重要な概念で、自身でライブラリを入れた際にもよく使う機能ですね!これまでに、サービスコンテナサービスプロバイダとファサードを理解するために必要な概念はお伝えしてきました。

今回は、満を持してファサードの使い方をお伝えしていきます。

まだサービスコンテナと、サービスプロバイダについて読んでいない方はこちらからお読みください。

そもそもファサードとは?

Laravelのコードを書いたり、見ていると

Route::get,Input::get('key')

のようなコードを見たことがあると思います。

これは一見するとクラスメソッドを実行しているように見えますが、呼び出しているクラスにこうしたメソッドがサービスコンテナに格納されているメソッドを実行しています。

サービスコンテナを使うことで、上記のようなシンプルな形でメソッドを呼び出すことがてきるのです。

Routeファサードの中身を見てみる

さて、ここでRouteの中身を見てみましょう。

先程お伝えした通り、facadeの中にはgetメソッドはありませんね。

class Route extends Facade{
      protected static function getFacadeAccessor(){
         return 'router';
}}

その代わりにあるgetFacadeAccessorメソッドですが、これがサービスコンテナを呼び出して、そこからgetメソッドを呼び出しているのです。

ですが、上記クラスではこれ以上のメソッドはなありません。

どのようにサービスコンテナを呼び出しているのかを、
継承元であるfacadeクラスを見てみましょう。

facadeクラスには、下記のようなマジックメソッドがあり、getメソッドは下記の処理になります。

public static function __callStatic($method, $args){
 $instance = static::getFacadeRoot();
if (! $instance) {
   throw new RuntimeException('A facade root has not been set.');
}
  return $instance->$method(...$args);
}

メソッドの最初でgefacaderoot()を呼んでいます。

ここでは、先程見たfetを引数に入れて、さらにresolvedFacadeInstanceを呼んでいます。

public static function getFacadeRoot(){
  return static::resolveFacadeInstance(static::getFacadeAccessor());
}

このメソッドでは、

もし与えられた引数(ここでは,router)がオブジェクトであればそのまま返し、次にすでにファサークラスで解決済みかどうかをチェックしています。

もし上記に入らない場合に、サービスコンテナからインスタンスを取得します。$appはIlluminateContractsFoundationApplicationとなっている。$app‘name’ は、app->make()の引数をつけた版です。

すなわち、サービスコンテナの解決ですね!

protected static function resolveFacadeInstance($name)
    {
        if (is_object($name)) {
            return $name;
        }

        if (isset(static::$resolvedInstance[$name])) {
            return static::$resolvedInstance[$name];
        }

        return static::$resolvedInstance[$name] = static::$app[$name];
    }

サービスコンテナとして解決されれば、あとはサービスコンテナに格納されたクラスを返し、そのインスタンスのメソッド(今回であればget())が呼び出されます。

なぜファサードを使うのか?

ファサードのメリットとして、下記が考えられます。

  1. 依存性の注入ができ、シンプルに記述ができる。
  2. サービスコンテナを返して、インスタンスにアクセスすることで、単純にインスタンス化する場合よりもメモリの使用量が減り、パフォーマンスの向上が見込めます。

Laravelデフォルトのファサードは?

illuminate/facadesにデフォルトのファサードがあります。

ファサードの作成

それでは、これまでの説明を使って、実際に自分で書いていきましょう。

まずは全体像の確認です。下記の6つのステップでオリジナルのファサードを作成していきます。

  1. クラスを作成
  2. サービスプロバイダーの作成
  3. サービスプロバイダーを登録
  4. ファサードクラスを作成
  5. エイリアスの設定

1,クラスを作成

namespace App\Services;

class Hello(){

public function say(){
    return echo "hello world";
  }
}

2,サービスプロバイダーの作成

php  artisan make:provider HelloServiceProvider

作成したサービスプロバイダーに
先程作成したクラスをサービスコンテナに結合するコードを記載します。
*作成したプロバイダのregisterメソッドに記載してください。

public function register(){
   $this->app()->bind('hello',
  'App\Services\Hello'
}

3,サービスプロバイダを登録

config/app.php の ‘providers’配列に先ほど作成したサービスプロバイダーを登録してください。

'providers' => [
:
  App\Providers\HelloServiceProvider::class,
  ],

4,ファサードの作成

ファサードクラスを継承したオリジナルのファサード(今回であればHello)を作成してください。

namespace App\Facades;

use Illuminate\Support\Facades\Facade;

class Hello extends Facade{
protected static function getFacadeAccessor(){
     return 'hello';
}
}

5,エイリアスの設定

config/app.phpのalias配列にファサードのエイリアスを登録してください。

 'aliases' => [
:
  'Hello' => App\Facades\Hello::class,
  ],

エイリアスの設定を済ませた段階で、ファサードとして、Hello::say()を使うことができます。
簡単ですね!! laravelって素晴らしいですね。

まとめ

ファサードクラスは使いこなせるとかなり便利なので、ぜひその仕組みを理解して自分だけのファサードを作ってみてくださいね。
ちなみにですが、laravelのファサードとデザインパターンのファサードは別物らしいです笑 Laravelの作者がtwitterで言及しています。

2 COMMENTS

コメントを残す