lumen DB-Facades

Facades 门面

app.php 中$app->withFacades()开启门面模式就可以使用DB类

public function withFacades($aliases = true, $userAliases = [])
{
    Facade::setFacadeApplication($this);

    if ($aliases) {
        $this->withAliases($userAliases);
    }
}

\Illuminate\Support\Facades\Facade::setFacadeApplication

可以看出,其实就是把app对象赋值给Facade类的app属性,而在Application实例话,启动容器的时候已经把db作为别名注入进去了,\Laravel\Lumen\Application::registerContainerAliases然后在使用DB类调用数据库函数的时候其实就是使用app对象app['db']这样调用数据库。

DB类实现Facade的一个方法,返回的就是一个数据库类的别名\Illuminate\Support\Facades\DB::getFacadeAccessor例如:

DB::select('SELECT *FROM users WHERE 1 LIMIT 1')

其实就是调用Facades类的__callStatic方法,__callStatic方法里\Illuminate\Support\Facades\Facade::getFacadeRoot获取一个db对象,然后调用相应的方法,把查询的参数传进去。

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

db别名绑定的是Illuminate\Database\DatabaseManager这个数据库管理类,这个类是一个公共类,同时支持其他数据库驱动,如'mysql', 'pgsql', 'sqlite', 'sqlsrv',默认在config.php配置的是mysql,在查询的时候就指的是mysql的驱动,如select查询调用DatabaseManager类的call方法,如果没有指定connections,会取默认的数据库连接,比如不同数据库之间的查询,由config文件的database.default这个控制,根据数据库名称从configure里面取出一个链接的配置类容。那么db是在什么时候注册进去的呢,这个其实只是在一开始做类一个绑定,在应用的时候通过make方法取出一个实例来。

protected function registerContainerAliases()
    {
        $this->aliases = [
            'Illuminate\Database\DatabaseManager' => 'db',
        ];
    }

public function make($abstract, array $parameters = [])
{
    $abstract = $this->getAlias($abstract);

    if (array_key_exists($abstract, $this->availableBindings) &&
        ! array_key_exists($this->availableBindings[$abstract], $this->ranServiceBinders)) {
        $this->{$method = $this->availableBindings[$abstract]}();

        $this->ranServiceBinders[$method] = true;
    }

    return parent::make($abstract, $parameters);
}

/**
* The available container bindings and their respective load methods.
*
* @var array
*/
public $availableBindings = [
    'db' => 'registerDatabaseBindings',
];

protected function registerDatabaseBindings()
    {
        $this->singleton('db', function () {
            return $this->loadComponent(
                'database', [
                    'Illuminate\Database\DatabaseServiceProvider',
                    'Illuminate\Pagination\PaginationServiceProvider',
                ], 'db'
            );
        });
    } 
    
    /**
     * \Illuminate\Database\DatabaseServiceProvider::registerConnectionServices
     * Register the primary database bindings.
     *
     * @return void
     */
    protected function registerConnectionServices()
    {
        // The connection factory is used to create the actual connection instances on
        // the database. We will inject the factory into the manager so that it may
        // make the connections while they are actually needed and not of before.
        $this->app->singleton('db.factory', function ($app) {
            return new ConnectionFactory($app);
        });

        // The database manager is used to resolve various connections, since multiple
        // connections might be managed. It also implements the connection resolver
        // interface which may be used by other components requiring connections.
        $this->app->singleton('db', function ($app) {
            return new DatabaseManager($app, $app['db.factory']);
        });

        $this->app->bind('db.connection', function ($app) {
            return $app['db']->connection();
        });
    }

DatabaseManager这里调用call方法的时候会去获取默认的connection,\Illuminate\Database\DatabaseManager::makeConnection这个方法就是为了获取一个数据库连接的实例,config, $name) 这里的factory就是ConnectionFactory类,调用它里面的make方法,参数就是数据库的配置数组,和名称,这里就是名称就是mysql,\Illuminate\Database\Connectors\ConnectionFactory::createConnection个方法就是去连接数据库了,MySqlConnection继承了\Illuminate\Database\Connection这个类,调用它的select方法执行sql。ConnectionFactory是一个生产连接的工厂类,\Illuminate\Database\ConnectionInterface这个接口在\Illuminate\Database\Connection基础类上实现了它,然后不同的数据库驱动又继承了基础的connection类。

ORM 对象关系模型

app.php 中$app->withEloquent()开启orm关系模式

和门面一样,在app对象实例化的时候已经绑定了db的别名,开启orm的时候通过make方法取出数据库的实例,db就是在make的时候去寻找系统已经绑定的数组,注入容器,运行加载的方法,比如db就是这个\Laravel\Lumen\Application::registerDatabaseBindings方法,这个方法里加载了数据库的配置文件以及注册数据库服务,返回一个db的实例。

class DatabaseServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Model::setConnectionResolver($this->app['db']);

        Model::setEventDispatcher($this->app['events']);
    }

    public function register()
    {
        Model::clearBootedModels();

        $this->registerConnectionServices();

        $this->registerEloquentFactory();

        $this->registerQueueableEntityResolver();
    }

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

        $this->app->bind('db.connection', function ($app) {
            return $app['db']->connection();
        });
    }

    protected function registerEloquentFactory()
    {
        $this->app->singleton(FakerGenerator::class, function ($app) {
            return FakerFactory::create($app['config']->get('app.faker_locale', 'en_US'));
        });

        $this->app->singleton(EloquentFactory::class, function ($app) {
            return EloquentFactory::construct(
                $app->make(FakerGenerator::class), $this->app->databasePath('factories')
            );
        });
    }

    protected function registerQueueableEntityResolver()
    {
        $this->app->singleton(EntityResolver::class, function () {
            return new QueueEntityResolver;
        });
    }
}

\Illuminate\Database\DatabaseServiceProvider注册的时候运行boot方法,db的实例在这设置给\Illuminate\Database\Eloquent\Model类中,register方法中先清除已启动的实例,接下来就是一系列数据库相关的注册到容器中,应用的时候,我们所有的模型类都会实现\Illuminate\Database\Eloquent\Model,它使用了其他orm操作运算的一些trait类(trait类会覆盖类继承的方法,当前类的中法又会覆盖trait中的方法,这也是php解决单继承做的一个扩展)。

你可能感兴趣的:(lumen DB-Facades)