My I/O

インプットしたことをアウトプットするブログ

Laravel5.5 ファサード

ファサードは、サービスコンテナで動くサービスの静的プロキシ。 サービスコンテナで提供されるサービスは、

  • コントローラのコンストラクタの引数
  • サービスプロバイダのbootの引数
  • $this->app->make()

などで利用できるが、静的に利用することで、

テストの行いやすさ・柔軟性を保ちながらも、簡潔で記述的

ファサード 5.5 Laravel

となる。

ファサードの多用注意

簡単に使用できるため使いすぎる傾向がある。 クラスが大きくなりすぎないよう、責任範囲を小さくするように気を払うこと。

依存注入を使用すれば、クラスが大きくなりすぎることに伴う、大きなコンストラクタの視覚的なフィードバックにより、この危険性は抑制されます。

依存注入=コンストラクタの引数を使う

DBのファサード利用例

use Illuminate\Support\Facades\DB;


$user =  DB::table('users')
            ->where('user_id', 1)
            ->get();

ファサード追跡

上のDBファサードを使ってレコードを取得する流れを追ってみました。

1 Illuminate\Support\Facades\DBにはtable()はない

親クラスを追跡。

namespace Illuminate\Support\Facades;

class DB extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'db';
    }
}

2. 親のFacadeクラスにもないが、__call()が定義されている

$instance = static::getFacadeRoot(); でコンテナに登録したDBコンテナのオブジェクトを取得しており、 return $instance->$method(...$args); でオブジェクトからtable()を実行している。

...$args ってなんだろう..。 ... って。文字列結合に使うドットを3つ並べるとなんなんだ..) ( getFacadeRoot() では resolveFacadeInstance() が呼ばれているだけ。 FacadeRoot という言葉を使っているのはなにを想定してだろうかな?)

    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);
    }
}

3. DBがどのオブジェクトと結合されているのか確認してtable()を存在を確かめる

// config/app.php
    'providers' => [

         ....
        Illuminate\Database\DatabaseServiceProvider::class,
// DatabaseServiceProvider.php

        $this->app->singleton('db', function ($app) {
            return new DatabaseManager($app, $app['db.factory']);
        });

table()はなく __call()内で$this->connection() (戻り値は\Illuminate\Database\Connectionインスタンス)

// DatabaseManager.php

    public function __call($method, $parameters)
    {
        return $this->connection()->$method(...$parameters);
    }

ありました!table() !

// \Illuminate\Database\Connection

    public function table($table)
    {
        return $this->query()->from($table);
    }

リアルタイムファサードを追う

時間切れで終えなかったのでまた今度。