Laravel 数据库基本操作

Laravel 数据库基本操作#

了解 Laravel 某个模块的内部实现,最好的切入点就是从 composer.json 开始,
从里面我们主要可以得到以下信息:

  • require 字段可以知道相关的依赖包
  • extra.laravel.providers 可以知道它的服务提供者的类名称,这个字段配置的类
    会被 laravel 自动加载执行

Laravel 扩展扩展功能通常都是以 ServiceProvider 的形式注入到 Laravel 项目中的。
所以我们如果要从代码内部层面了解某个扩展包的内部逻辑,都是从 ServiceProvider 都是切入点去了解。

Laravel 数据库操作的服务提供者类为 Illuminate\Database\DatabaseServiceProvider

Laravel 数据库操作主要由以下几个部分组成:

  • Connector 数据库连接器,它负责创建具体的数据库连接
  • ConnectionFactory 连接创建器,它的主要作用就是根据配置的不同,创建对应的
    Connection
  • DatabaseManager 数据库管理器,数据操作的组织类,它就是名为 DB 的 facade
  • DatabaseTransactionsManager 数据库操作事务管理类,主要负责事务相关操作

Connectors 数据库连接器#

连接器的作用是用来和数据库建立连接,其其底层依赖 PDO。目前 Laravel 支持 4 中类型的
数据库:

  • MySqlConnector 创建 MySqlConnection
  • PostgresConnector 创建 PostgresConnection
  • SQLiteConnector 创建 SQLiteConnection
  • SqlServerConnector 创建 SqlServerConnection

以 mysql 为例介绍整个数据库连接创建的过程

  • 首先根据 database 的配置生成 PDO 创建连接需要的 dsn 字符串
  • 合并 PDO 的设置项,设置项都是以 PDO::ATTR_xxxx 开头,具体可以查看 php 手册
  • 创建 PDO 连接
  • 执行 use ${database} 选择数据库
  • 如果设置了 isolation_level ,会执行 SET SESSION TRANSACTION ISOLATION LEVEL 设置事务的级别
  • set names 设置连接的字符编码
  • set time_zone= 时区设置
  • set session sql_mode 设置 sql_mode

ConnectionFactory 连接创建器#

ConnectionFactory 作用特别简单,就是根据 database 配置的不同的 driver 实例化上面介绍的 4 中数据库类型的连接器。

如果想要想要使用自定义的数据库连接器,可以在容器里面注册名为 db.connector.${driver} 创建器。

DatabaseManager#

DatabaseManager 是我们操作数据的入口,负责把上面介绍的各个功能类串联起来,在操作数据库的业务逻辑中,我们都是透过 DatabaseManager 来和数据库打交道。

我们在业务逻辑中用的 DB facade 本质就是这个类。它通过魔术方法 __call,把具体的数据库的操作代理到具体的 Connection 上去执行了。


    /**
     * Dynamically pass methods to the default connection.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        return $this->connection()->$method(...$parameters);
    }

例如我们执行 DB::select('select * from users where active = ?', [1]);
具体的过程如下

  • 创建一个默认的数据库连接
  • 调用数据库连接对象上的 query 方法。

数据库操作相关的主要功能模块基本就是以上这个,下面介绍下如何的使用

use Illuminate\Config\Repository;
use Illuminate\Database\Connectors\ConnectionFactory;
use Illuminate\Database\DatabaseManager;
use Illuminate\Foundation\Application;
// 配置
$repository = new Repository();
$repository->set('database', [
    'default' => 'mysql',
    'connections' => [
        'mysql' => [
            'driver' => 'mysql',
            'host' => '127.0.0.1',
            'port' => '3306',
            'database' => 'app',
            'username' => 'root',
            'password' => '123456',
            'unix_socket' => '',
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => [],
        ]
    ],
]);


// 创建 Application 对象
$app = new Application();

// 数据库的配置保存到 Application 中
$app->instance('config',$repository);

// 创建数据库连接器
$connectionFactory = new ConnectionFactory($app);

// 创建数据库管理对象
$db = new DatabaseManager($app,$connectionFactory);

// 执行查询的 SQL
$list = $db->select("show databases");

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 1

你好,我看到这个:如果想要想要使用自定义的数据库连接器,可以在容器里面注册名为 db.connector.${driver} 创建器。这个具体怎么写啊?我现在需要使用 doris 数据库,虽然是 mysql 协议,但是不支持 mysqlconnector 的 options 选项,因此需要单独创建一个 conector,继承自 MySqlConnector,然后进行注册,我这样写不行是怎么回事呢? D:\WWW\xxx\app\Providers\DorisConnectorServiceProvider.php

  public function register()
    {
        $this->app->resolving('db.connector.doris', function ($db) {
            return new DorisConnector();
        });
    }```

下面是DorisConnector的代码:

<?php

namespace App\Connectors;

use Illuminate\Database\Connectors\MySqlConnector;

class DorisConnector extends MySqlConnector { public function connect(array $config) { $dsn = $this->getDsn($config);

    // We need to grab the PDO options that should be used while making the brand
    // new connection instance. The PDO options control various aspects of the
    // connection's behavior, and some might be specified by the developers.
    $connection = $this->createConnection($dsn, $config, []);

    if (!empty($config['database'])) {
        $connection->exec("use `{$config['database']}`;");
    }

    $this->configureEncoding($connection, $config);

    // Next, we will check to see if a timezone has been specified in this config
    // and if it has we will issue a statement to modify the timezone with the
    // database. Setting this DB timezone is an optional configuration item.
    $this->configureTimezone($connection, $config);

    return $connection;
}

} ```

1年前 评论