Closed3

Laravelのソースを読む DB Facade編

白湯白湯

vendor/laravel/framework/src/Illuminate/Support/Facades/DB.php を読む

<?php

namespace Illuminate\Support\Facades;

class DB extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'db';
    }
}

定義されているメソッドは getFacadeAccessor のみ。
ここでは db という文字列を返している。

Facadeクラスを読んでみる。(コードは今回読むところ以外は削除)

<?php

namespace Illuminate\Support\Facades;

abstract class Facade
{
    protected static $app;

    protected static $resolvedInstance;

    protected static $cached = true;

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

    protected static function getFacadeAccessor()
    {
        throw new RuntimeException('Facade does not implement getFacadeAccessor method.');
    }

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

        if (static::$app) {
            if (static::$cached) {
                return static::$resolvedInstance[$name] = static::$app[$name];
            }

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

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

なんかいろいろメソッドはあるけど、基本的には __callStatic が呼ばれることになる。

<?php

\Illuminate\Support\Facades\DB::table('tableName')->get();

こんなコードの場合、DBクラスには table メソッドは定義されていないので、 __callStatic が呼ばれる。
__callStaticの中で、 getFacadeRootからインスタンスを取得し、tableメソッドを実行している。

resolveFacadeInstanceでコンテナからインスタンスを取得しているっぽい。
getFacadeAccessordbを返すので、static::$app['db']getFacadeRootで得られるクラスのようだ。

static::$app\Illuminate\Contracts\Foundation\Applicationであり、vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/RegisterFacades.phpでセットされれているみたい。

static::$app['db']vendor/laravel/framework/src/Illuminate/Database/DatabaseServiceProvider.phpでバインドされている。

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

DatabaseManagerクラスには table メソッドは定義されていない。

table メソッドはConnectionクラスに定義してあり、DatabaseManagerクラスの __call メソッドでConnectionクラスのインスタンスを取得して実行している。

class DatabaseManager implements ConnectionResolverInterface
{
    public function __call($method, $parameters)
    {
        // connection()でConnectionクラスのインスタンスを取得している。
        return $this->connection()->$method(...$parameters);
    }
}
このスクラップは2022/06/22にクローズされました