illuminate/database 使用 一

2023-10-24 05:20
文章标签 使用 database illuminate

本文主要是介绍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 使用 一的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/272955

相关文章

使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)

《使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)》在现代软件开发中,处理JSON数据是一项非常常见的任务,无论是从API接口获取数据,还是将数据存储为JSON格式,解析... 目录1. 背景介绍1.1 jsON简介1.2 实际案例2. 准备工作2.1 环境搭建2.1.1 添加

MySQL中删除重复数据SQL的三种写法

《MySQL中删除重复数据SQL的三种写法》:本文主要介绍MySQL中删除重复数据SQL的三种写法,文中通过代码示例讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下... 目录方法一:使用 left join + 子查询删除重复数据(推荐)方法二:创建临时表(需分多步执行,逻辑清晰,但会

如何使用celery进行异步处理和定时任务(django)

《如何使用celery进行异步处理和定时任务(django)》文章介绍了Celery的基本概念、安装方法、如何使用Celery进行异步任务处理以及如何设置定时任务,通过Celery,可以在Web应用中... 目录一、celery的作用二、安装celery三、使用celery 异步执行任务四、使用celery

使用Python绘制蛇年春节祝福艺术图

《使用Python绘制蛇年春节祝福艺术图》:本文主要介绍如何使用Python的Matplotlib库绘制一幅富有创意的“蛇年有福”艺术图,这幅图结合了数字,蛇形,花朵等装饰,需要的可以参考下... 目录1. 绘图的基本概念2. 准备工作3. 实现代码解析3.1 设置绘图画布3.2 绘制数字“2025”3.3

Jsoncpp的安装与使用方式

《Jsoncpp的安装与使用方式》JsonCpp是一个用于解析和生成JSON数据的C++库,它支持解析JSON文件或字符串到C++对象,以及将C++对象序列化回JSON格式,安装JsonCpp可以通过... 目录安装jsoncppJsoncpp的使用Value类构造函数检测保存的数据类型提取数据对json数

python使用watchdog实现文件资源监控

《python使用watchdog实现文件资源监控》watchdog支持跨平台文件资源监控,可以检测指定文件夹下文件及文件夹变动,下面我们来看看Python如何使用watchdog实现文件资源监控吧... python文件监控库watchdogs简介随着Python在各种应用领域中的广泛使用,其生态环境也

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

springboot整合 xxl-job及使用步骤

《springboot整合xxl-job及使用步骤》XXL-JOB是一个分布式任务调度平台,用于解决分布式系统中的任务调度和管理问题,文章详细介绍了XXL-JOB的架构,包括调度中心、执行器和Web... 目录一、xxl-job是什么二、使用步骤1. 下载并运行管理端代码2. 访问管理页面,确认是否启动成功

Mysql 中的多表连接和连接类型详解

《Mysql中的多表连接和连接类型详解》这篇文章详细介绍了MySQL中的多表连接及其各种类型,包括内连接、左连接、右连接、全外连接、自连接和交叉连接,通过这些连接方式,可以将分散在不同表中的相关数据... 目录什么是多表连接?1. 内连接(INNER JOIN)2. 左连接(LEFT JOIN 或 LEFT

使用Nginx来共享文件的详细教程

《使用Nginx来共享文件的详细教程》有时我们想共享电脑上的某些文件,一个比较方便的做法是,开一个HTTP服务,指向文件所在的目录,这次我们用nginx来实现这个需求,本文将通过代码示例一步步教你使用... 在本教程中,我们将向您展示如何使用开源 Web 服务器 Nginx 设置文件共享服务器步骤 0 —