我独自走进 Laravel5.5 的❤(九)
关于 laravel 的数据库驱动启动流程
-
配置
我们都知道,要配置 laravel 项目的数据库,要在 .env 中配置下面几个参数DB_CONNECTION DB_HOST DB_PORT DB_DATABASE DB_USERNAME DB_PASSWORD
我们也知道这几个参数会在配置文件 config/database.php 中被引用
'connections' => [ 'sqlite' => [ 'driver' => 'sqlite', 'database' => env('DB_DATABASE', database_path('database.sqlite')), 'prefix' => '', ], 'mysql' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'unix_socket' => env('DB_SOCKET', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'strict' => false, 'engine' => null, ], 'pgsql' => [ 'driver' => 'pgsql', 'host' => env('DB_HOST', '127.0.0.1'), 'port' => env('DB_PORT', '5432'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'prefix' => '', 'schema' => 'public', 'sslmode' => 'prefer', ], 'sqlsrv' => [ 'driver' => 'sqlsrv', 'host' => env('DB_HOST', 'localhost'), 'port' => env('DB_PORT', '1433'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'prefix' => '', ], ],
好的,眼前不止苟且,一起深入进去。
2.数据库服务提供者
在 config/app.php 中的 providers 中有注册Illuminate\Database\DatabaseServiceProvider::class,
在Illuminate\Database\DatabaseServiceProvider::class,
注册时会触发注册数据库连接服务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(); }); }
3.连接工厂
在连接工厂中,会根据配置的驱动不同生成不同的数据库连接器,真香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']}]"); }
4.连接器
在各个 Connector 中都会有一个连接方法 connect,
在 connect() 中会生成一个 连接$connection = $this->createConnection( **$this->getDsn($config),** $config, $this->getOptions($config) );
注意这里有一个 getDsn(),这个方法会返回一个特定的 PDO 驱动程序的名称,例如 mysql 会返回
mysql:host=127.0.0.1;port=3306;dbname=homestead"
4.1关于createConnection()
public function createConnection($dsn, array $config, array $options) { list($username, $password) = [ $config['username'] ?? null, $config['password'] ?? null, ]; try { return $this->createPdoConnection( $dsn, $username, $password, $options ); } catch (Exception $e) { return $this->tryAgainIfCausedByLostConnection( $e, $dsn, $username, $password, $options ); } }
这里可以看到获取数据库用户名和密码,然后创建一个 pdo 连接
4.2关于createPdoConnection()protected function createPdoConnection($dsn, $username, $password, $options) { if (class_exists(PDOConnection::class) && ! $this->isPersistentConnection($options)) { return new **PDOConnection($dsn, $username, $password, $options)**; } return new PDO($dsn, $username, $password, $options); }
4.3关于 PDOConnection
Doctrine/DBAL/Driver/PDOConnection::class 其实是一个继承了 PDO 的类,重新封装了 exec()、query()等一些方法
具体可以 github 上观摩。
https://github.com/doctrine/dbal/blob/mast...
<-------------------------------------------------------------------------- End ---------------------------------------------------------------------->
至此,
致敬知识。
本作品采用《CC 协议》,转载必须注明作者和本文链接
nice