illuminate/database 使用 一

编程入门 行业动态 更新时间:2024-10-23 14:25:53

<a href=https://www.elefans.com/category/jswz/34/1761871.html style=illuminate/database 使用 一"/>

illuminate/database 使用 一

illuminate/database 是完整的php数据库工具包,即ORM(Object-Relational Mapping)类库。

提供丰富的查询构造器,和多个驱动的服务。作为Laravel的数据库层使用,也可以单独使用。

一 使用

加载composer之后,创建Illuminate\Database\Capsule\Manager对象,配置连接数据后可将其全局化,之后调用全局化的变量使用构造方法等进行查询。

二 代码

require_once './vendor/autoload.php';use Illuminate\Container\Container;
use Illuminate\Database\Capsule\Manager as DB;
use Illuminate\Events\Dispatcher;class BasedDB
{private $config;public function __construct($config){$this->config = ['driver' => 'mysql','host' => $config["host"],'database' => $config["database"],'username' => $config["username"],'password' => $config["password"],'charset' => $config["charset"],'collation' => $config["collation"],'prefix' => $config["prefix"],];$this->init();}public function init(){$db = new DB();$db->addConnection($this->config);$db->setEventDispatcher(new Dispatcher(new Container));$db->setAsGlobal(); //设置静态全局可用$db->bootEloquent();}}class TestDB extends BasedDB
{public function test1(){//构造查询$info = DB::table('userinfo')->where('id', '=', 2)->get();var_dump($info);}
}
$config = ['driver' => 'mysql','host' => 'localhost','database' => 'test','username' => 'root','password' => 'qwe110110','charset' => 'utf8','collation' => 'utf8_general_ci','prefix' => '',
];
$t = new TestDB($config);
$t->test1();

三 原理

从代码可见从Illuminate\Database\Capsule\Manager::addConnection($config)开始。

addConnection仅设置配置。该类的构造参数中包含Illuminate\Container\Container类,通过Manager::setupContainer()函数传入Container类对象,获取绑定的配置。

Container类中Container::bound()判断是否有绑定的内容。使用Container::bind()绑定内容,会删除共享实例中对应的别名内容。绑定时若为指定绑定类的具体类或者说闭包,会自动处理,若未执行则实际处理类为指定的类,利用反射返回对应实例,否则直接返回已有实例。

Manager::setEventDispatcher() 从字面意思是设置事件调度程序。传入参数Illuminate\Events\Dispatcher类实例。通过查看代码,Dispatcher可以用Dispatcher::listen()、Dispatcher::push()、Dispatcher::dispatch()、Dispatcher::until()可以设置监听或调度监听。

Manager::setAsGlobal()将Manager全局化,可以用调用静态对象方法调用。

Manager::bootEloquent()启动Eloquent,其中调用Manager::getEventDispatcher()获取默认的程序调度,Eloquent::setEventDispatcher设置Eloquent的事件调度。Manager::getEventDispatcher()获取绑定的events内容。

到此为止初始化结束,没有出现获取pdo的内容。

调用Manager::table()开始查询,通过调用Manager自己的静态类调用connection,即static::$instance->connection()。

之后调用DatabaseManager::connection()方法。

DatabaseManager通过解析传入的配置名获取配置。若配置名为空则默认为default,可以调用DatabaseManager::setDefaultConnection()设置默认配置名。根据配置名获取配置,通过\Illuminate\Database\Connectors\ConnectionFactory工厂类匹配对应驱动,返回对应pdo对象。

比如返回Illuminate\Database\MySqlConnector对象。该类处理对应驱动特殊处理方法,比如数据库连接、设置事务隔离级别等。

table方法最后调用的是Illuminate\Database\Connection::table(),其为MySqlConnector父类。DatabaseManager::__call($method, $parameters)处理传如的数据并执行,该方法实际返回ConnectionFactory类创建的Illuminate\Database\Query\Builder对象,模式构建器调用结束的时候,将构造器对象作为参数,整合成查询字符串执行查询。

四 源码

1、初始化

根据代码可以绑定config类,或者自定义配置;可以设置events。

//Illuminate\Database\Capsule\Manageruse Illuminate\Container\Container;class Manager
{use CapsuleManagerTrait;protected $manager;/*** Create a new database capsule manager.** @param  \Illuminate\Container\Container|null  $container* @return void*/public function __construct(Container $container = null){$this->setupContainer($container ?: new Container);// Once we have the container setup, we will setup the default configuration// options in the container "config" binding. This will make the database// manager work correctly out of the box without extreme configuration.$this->setupDefaultConfiguration();$this->setupManager();}/*** Register a connection with the manager.** @param  array  $config* @param  string  $name* @return void*/public function addConnection(array $config, $name = 'default'){$connections = $this->container['config']['database.connections'];$connections[$name] = $config;$this->container['config']['database.connections'] = $connections;}/*** Get the current event dispatcher instance.** @return \Illuminate\Contracts\Events\Dispatcher|null*/public function getEventDispatcher(){if ($this->container->bound('events')) {return $this->container['events'];}}/*** Setup the default database configuration options.** @return void*/protected function setupDefaultConfiguration(){$this->container['config']['database.fetch'] = PDO::FETCH_OBJ;$this->container['config']['database.default'] = 'default';}/*** Set the event dispatcher instance to be used by connections.** @param  \Illuminate\Contracts\Events\Dispatcher  $dispatcher* @return void*/public function setEventDispatcher(Dispatcher $dispatcher){$this->container->instance('events', $dispatcher);}/*** Bootstrap Eloquent so it is ready for usage.** @return void*/public function bootEloquent(){Eloquent::setConnectionResolver($this->manager);// If we have an event dispatcher instance, we will go ahead and register it// with the Eloquent ORM, allowing for model callbacks while creating and// updating "model" instances; however, it is not necessary to operate.if ($dispatcher = $this->getEventDispatcher()) {Eloquent::setEventDispatcher($dispatcher);}}
}//Illuminate\Support\Traits\CapsuleManagerTrait
trait CapsuleManagerTrait
{/*** Make this capsule instance available globally.** @return void*/public function setAsGlobal(){static::$instance = $this;}/*** Setup the IoC container instance.** @param  \Illuminate\Contracts\Container\Container  $container* @return void*/protected function setupContainer(Container $container){$this->container = $container;if (! $this->container->bound('config')) {$this->container->instance('config', new Fluent);}}
}//\Illuminate\Contracts\Container\Container
use Illuminate\Contracts\Container\Container as ContainerContract;
class Container implements ArrayAccess, ContainerContract
{/*** Determine if the given abstract type has been bound.** @param  string  $abstract* @return bool*/public function bound($abstract){return isset($this->bindings[$abstract]) ||isset($this->instances[$abstract]) ||$this->isAlias($abstract);}/*** Register a binding with the container.** @param  string  $abstract* @param  \Closure|string|null  $concrete* @param  bool  $shared* @return void** @throws \TypeError*/public function bind($abstract, $concrete = null, $shared = false){$this->dropStaleInstances($abstract);// If no concrete type was given, we will simply set the concrete type to the// abstract type. After that, the concrete type to be registered as shared// without being forced to state their classes in both of the parameters.if (is_null($concrete)) {$concrete = $abstract;}// If the factory is not a Closure, it means it is just a class name which is// bound into this container to the abstract type and we will just wrap it// up inside its own Closure to give us more convenience when extending.if (! $concrete instanceof Closure) {if (! is_string($concrete)) {throw new TypeError(self::class.'::bind(): Argument #2 ($concrete) must be of type Closure|string|null');}$concrete = $this->getClosure($abstract, $concrete);}$this->bindings[$abstract] = compact('concrete', 'shared');// If the abstract type was already resolved in this container we'll fire the// rebound listener so that any objects which have already gotten resolved// can have their copy of the object updated via the listener callbacks.if ($this->resolved($abstract)) {$this->rebound($abstract);}}/*** Register an existing instance as shared in the container.** @param  string  $abstract* @param  mixed  $instance* @return mixed*/public function instance($abstract, $instance){$this->removeAbstractAlias($abstract);$isBound = $this->bound($abstract);unset($this->aliases[$abstract]);// We'll check to determine if this type has been bound before, and if it has// we will fire the rebound callbacks registered with the container and it// can be updated with consuming classes that have gotten resolved here.$this->instances[$abstract] = $instance;if ($isBound) {$this->rebound($abstract);}return $instance;}/*** Remove an alias from the contextual binding alias cache.** @param  string  $searched* @return void*/protected function removeAbstractAlias($searched){if (! isset($this->aliases[$searched])) {return;}foreach ($this->abstractAliases as $abstract => $aliases) {foreach ($aliases as $index => $alias) {if ($alias == $searched) {unset($this->abstractAliases[$abstract][$index]);}}}}
}

2、构造器

//Illuminate\Database\Capsule\Manager
use Illuminate\Database\DatabaseManager;
class Manager
{protected $manager;/*** Create a new database capsule manager.** @param  \Illuminate\Container\Container|null  $container* @return void*/public function __construct(Container $container = null){$this->setupContainer($container ?: new Container);// Once we have the container setup, we will setup the default configuration// options in the container "config" binding. This will make the database// manager work correctly out of the box without extreme configuration.$this->setupDefaultConfiguration();$this->setupManager();}/*** Build the database manager instance.** @return void*/protected function setupManager(){$factory = new ConnectionFactory($this->container);$this->manager = new DatabaseManager($this->container, $factory);}/*** Dynamically pass methods to the default connection.** @param  string  $method* @param  array  $parameters* @return mixed*/public static function __callStatic($method, $parameters){return static::connection()->$method(...$parameters);}/*** Get a connection instance from the global manager.** @param  string|null  $connection* @return \Illuminate\Database\Connection*/public static function connection($connection = null){return static::$instance->getConnection($connection);}/*** Get a registered connection instance.** @param  string|null  $name* @return \Illuminate\Database\Connection*/public function getConnection($name = null){return $this->manager->connection($name);}/*** Get a fluent query builder instance.** @param  \Closure|\Illuminate\Database\Query\Builder|string  $table* @param  string|null  $as* @param  string|null  $connection* @return \Illuminate\Database\Query\Builder*/public static function table($table, $as = null, $connection = null){return static::$instance->connection($connection)->table($table, $as);}
}//Illuminate\Database\DatabaseManager
use Illuminate\Database\Connectors\ConnectionFactory;
/*** @mixin \Illuminate\Database\Connection*/
class DatabaseManager implements ConnectionResolverInterface
{public function __construct($app, ConnectionFactory $factory){$this->app = $app;$this->factory = $factory;$this->reconnector = function ($connection) {$this->reconnect($connection->getNameWithReadWriteType());};}/*** Get a database connection instance.** @param  string|null  $name* @return \Illuminate\Database\Connection*/public function connection($name = null){[$database, $type] = $this->parseConnectionName($name);$name = $name ?: $database;// If we haven't created this connection, we'll create it based on the config// provided in the application. Once we've created the connections we will// set the "fetch mode" for PDO which determines the query return types.if (! isset($this->connections[$name])) {$this->connections[$name] = $this->configure($this->makeConnection($database), $type);}return $this->connections[$name];}/*** Make the database connection instance.** @param  string  $name* @return \Illuminate\Database\Connection*/protected function makeConnection($name){$config = $this->configuration($name);// First we will check by the connection name to see if an extension has been// registered specifically for that connection. If it has we will call the// Closure and pass it the config allowing it to resolve the connection.if (isset($this->extensions[$name])) {return call_user_func($this->extensions[$name], $config, $name);}// Next we will check to see if an extension has been registered for a driver// and will call the Closure if so, which allows us to have a more generic// resolver for the drivers themselves which applies to all connections.if (isset($this->extensions[$driver = $config['driver']])) {return call_user_func($this->extensions[$driver], $config, $name);}return $this->factory->make($config, $name);}
}//Illuminate\Database\Connectors\ConnectionFactory
class ConnectionFactory
{/*** Establish a PDO connection based on the configuration.** @param  array  $config* @param  string|null  $name* @return \Illuminate\Database\Connection*/public function make(array $config, $name = null){$config = $this->parseConfig($config, $name);if (isset($config['read'])) {return $this->createReadWriteConnection($config);}return $this->createSingleConnection($config());}/*** Parse and prepare the database configuration.** @param  array  $config* @param  string  $name* @return array*/protected function parseConfig(array $config, $name){return Arr::add(Arr::add($config, 'prefix', ''), 'name', $name);}/*** Create a read / write database connection instance.** @param  array  $config* @return \Illuminate\Database\Connection*/protected function createReadWriteConnection(array $config){$connection = $this->createSingleConnection($this->getWriteConfig($config));return $connection->setReadPdo($this->createReadPdo($config));}/*** Create a read / write database connection instance.** @param  array  $config* @return \Illuminate\Database\Connection*/protected function createReadWriteConnection(array $config){$connection = $this->createSingleConnection($this->getWriteConfig($config));return $connection->setReadPdo($this->createReadPdo($config));}/*** Create a single database connection instance.** @param  array  $config* @return \Illuminate\Database\Connection*/protected function createSingleConnection(array $config){$pdo = $this->createPdoResolver($config);return $this->createConnection($config['driver'], $pdo, $config['database'], $config['prefix'], $config);}/*** Get the write configuration for a read / write connection.** @param  array  $config* @return array*/protected function getWriteConfig(array $config){return $this->mergeReadWriteConfig($config, $this->getReadWriteConfig($config, 'write'));}/*** Merge a configuration for a read / write connection.** @param  array  $config* @param  array  $merge* @return array*/protected function mergeReadWriteConfig(array $config, array $merge){return Arr::except(array_merge($config, $merge), ['read', 'write']);}/*** Get a read / write level configuration.** @param  array  $config* @param  string  $type* @return array*/protected function getReadWriteConfig(array $config, $type){return isset($config[$type][0])? Arr::random($config[$type]): $config[$type];}/*** Create a single database connection instance.** @param  array  $config* @return \Illuminate\Database\Connection*/protected function createSingleConnection(array $config){$pdo = $this->createPdoResolver($config);return $this->createConnection($config['driver'], $pdo, $config['database'], $config['prefix'], $config);}/*** Create a connector instance based on the configuration.** @param  array  $config* @return \Illuminate\Database\Connectors\ConnectorInterface** @throws \InvalidArgumentException*/public function createConnector(array $config){if (!isset($config['driver'])) {throw new InvalidArgumentException('A driver must be specified.');}if ($this->container->bound($key = "db.connector.{$config['driver']}")) {return $this->container->make($key);}switch ($config['driver']) {case 'mysql':return new MySqlConnector;case 'pgsql':return new PostgresConnector;case 'sqlite':return new SQLiteConnector;case 'sqlsrv':return new SqlServerConnector;}throw new InvalidArgumentException("Unsupported driver [{$config['driver']}].");}/*** Create a new connection instance.** @param  string  $driver* @param  \PDO|\Closure  $connection* @param  string  $database* @param  string  $prefix* @param  array  $config* @return \Illuminate\Database\Connection** @throws \InvalidArgumentException*/protected function createConnection($driver, $connection, $database, $prefix = '', array $config = []){if ($resolver = Connection::getResolver($driver)) {return $resolver($connection, $database, $prefix, $config);}switch ($driver) {case 'mysql':return new MySqlConnection($connection, $database, $prefix, $config);case 'pgsql':return new PostgresConnection($connection, $database, $prefix, $config);case 'sqlite':return new SQLiteConnection($connection, $database, $prefix, $config);case 'sqlsrv':return new SqlServerConnection($connection, $database, $prefix, $config);}throw new InvalidArgumentException("Unsupported driver [{$driver}].");}
}//Illuminate\Database\MySqlConnection
class MySqlConnection extends Connection
{
}//Illuminate\Database\Connection
use Illuminate\Database\Query\Builder as QueryBuilder;
class Connection implements ConnectionInterface
{/*** Begin a fluent query against a database table.** @param  \Closure|\Illuminate\Database\Query\Builder|string  $table* @param  string|null  $as* @return \Illuminate\Database\Query\Builder*/public function table($table, $as = null){return $this->query()->from($table, $as);}/*** Get a new query builder instance.** @return \Illuminate\Database\Query\Builder*/public function query(){return new QueryBuilder($this, $this->getQueryGrammar(), $this->getPostProcessor());}
}//Illuminate\Database\Query\Builder
class Builder
{/*** Set the table which the query is targeting.** @param  \Closure|\Illuminate\Database\Query\Builder|string  $table* @param  string|null  $as* @return $this*/public function from($table, $as = null){if ($this->isQueryable($table)) {return $this->fromSub($table, $as);}$this->from = $as ? "{$table} as {$as}" : $table;return $this;}/*** Determine if the value is a query builder instance or a Closure.** @param  mixed  $value* @return bool*/protected function isQueryable($value){return $value instanceof self ||$value instanceof EloquentBuilder ||$value instanceof Relation ||$value instanceof Closure;}/*** Makes "from" fetch from a subquery.** @param  \Closure|\Illuminate\Database\Query\Builder|string  $query* @param  string  $as* @return $this** @throws \InvalidArgumentException*/public function fromSub($query, $as){[$query, $bindings] = $this->createSub($query);return $this->fromRaw('('.$query.') as '.$this->grammar->wrapTable($as), $bindings);}……//之后都是构建构造器的 没调试 看的也不是太懂
}

注:

本地使用php版本7.4,illuminate/database为v8.83.27

illuminate/database composer地址:illuminate/database - Packagist

illuminate/database girbub地址:GitHub - illuminate/database: [READ ONLY] Subtree split of the Illuminate Database component (see laravel/framework)

更多推荐

illuminate/database 使用 一

本文发布于:2023-12-04 11:39:01,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1660791.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:illuminate   database

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!