CodeIgnitor 3.0.x 之 db 类实现机制

  • Codeignitor 的 db 类的说明,锻炼一下文字表达能力

  • 一般的使用场景:

class home extends Base_Controller
{    
    public function test()  
    {
        $this->load->model('my/User_model');
    }
}

class User_model extend CI_Model  
{
    public function __construct()  
    {
       $this->db = $this->load->database('my', TRUE);
    }
}

class CI_Model
{
    public function __get($key)  
    {  
        return get_instance()->$key;  
    }
}
  • 在 controller 中加载 model 类

  • 在 model 中加载 db,获得 db 对象,可以用来查询 sql

    • model 中的 load 对象是从 controller 中获取的
    • db 对象的类型是 CI_DB_mysqli_driver,这是 load 对象根据默认配置创建的 mysql 数据库查询对象
    • 默认配置文件在 /config/database.php,按照框架约定配置好数据库参数
  • database.php 内容如下:

$active_group = 'default';  
$query_builder = TRUE;
$db['default'] = array(
    $db['myche'] = array(  
         'dsn' => '',  
         'hostname' => $_SERVER['DB_MY_HOST'],  
         'username' => $_SERVER['DB_MY_USER'],  
         'password' => $_SERVER['DB_MY_PASS'],  
         'database' => $_SERVER['DB_MY_NAME'],  
         'dbdriver' => 'mysqli',  
         'dbprefix' => '',  
         'pconnect' => FALSE,  
         'db_debug' => (ENVIRONMENT !== 'production'),  
         'cache_on' => FALSE,  
         'cachedir' => '',  
         'char_set' => 'utf8',  
         'dbcollat' => 'utf8_general_ci',  
         'swap_pre' => '',  
         'encrypt' => FALSE,  
         'compress' => FALSE,  
         'stricton' => FALSE,  
         'failover' => array(),  
         'save_queries' => (ENVIRONMENT !== 'production')  
    );
);
  • CI_DB_mysqli_driver 继承自 CI_DBCI_DB 类使用了一种奇怪的方式实现的,这个类是在一个叫做DB的函数内声明的,根据 $query_builder=true 的配置来决定声明CI_DB的父类是CI_DB_driver还是CI_DB_query_builder,两者的区别就是后者继承自前者并在前者的基础上实现了常用语句的链式调用方法。按照声明处注释所说,CI_DB类可以理解为 CI_DB_driverCI_DB_query_builder 的别名。

  • CI_DB_mysqli_driver的创建过程:

    • 在 load 对象的 database 方法中调用 DB 函数
    • 在 DB 函数中
      • 声明 CI_DB,根据 $query_builder=true 的配置来决定CI_DB的父类是CI_DB_driver还是CI_DB_query_builder
      • 根据 dbdriver 配置加载数据库驱动类文件,并实例化 CI_DB_mysqli_driver,并返回此对象。
  • DB 函数的实现

function &DB($params = '', $query_builder_override = NULL)  
{
    require_once(BASEPATH.'database/DB_driver.php');
    
    if ( ! isset($query_builder) OR $query_builder === TRUE)
	{
		require_once(BASEPATH.'database/DB_query_builder.php');
		if ( ! class_exists('CI_DB', FALSE))
		{
			/**
			 * CI_DB
			 *
			 * Acts as an alias for both CI_DB_driver and CI_DB_query_builder.
			 *
			 * @see	CI_DB_query_builder
			 * @see	CI_DB_driver
			 */
			class CI_DB extends CI_DB_query_builder { }
		}
	}
	elseif ( ! class_exists('CI_DB', FALSE))
	{
		class CI_DB extends CI_DB_driver { }
	}
    
    // Load the DB driver  
    $driver_file = BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_driver.php';
    require_once($driver_file);
    
    // Instantiate the DB adapter
	$driver = 'CI_DB_'.$params['dbdriver'].'_driver';
	$DB = new $driver($params);
    
    return $DB;
}
  • CI_DB_mysqli_driver 最终是继承自 CI_DB_driver 这个抽象类。CI_DB_driver 定义了数据库驱动类需要实现的一些通用方法,具体的驱动类比如 CI_DB_mysqli_driver 则实现了这些方法。

  • CI_DB_driver 关键方法定义

abstract class CI_DB_driver {
    // db 连接
    function db_connect() {}
        
    // db 长连接
    function db_pconnect() {}
    
    // 设置连接字符集编码
    function _db_set_charset() {}
    
    // 选择数据库
    function db_select() {}
    
    // 开始事务
    function _trans_begin() {}
    
    // 回滚事务
    function _trans_rollback() {}
    
    // 提交事务
    function _trans_commit() {}
    
    // 执行查询
    function _execute($sql) {}
}

上面的描述总结为下图:

CodeIgnitor 3.0.x 之 db 类实现机制

  • CI_DB_mysqli_driver 的部分实现
class CI_DB_mysqli_driver extends CI_DB {
    // 连接数据库
    public function db_connect($persistent = FALSE)  
    {
        // Do we have a socket path?
		if ($this->hostname[0] === '/')
		{
			$hostname = NULL;
			$port = NULL;
			$socket = $this->hostname;
		}
		else
		{
			// Persistent connection support was added in PHP 5.3.0
			$hostname = ($persistent === TRUE && is_php('5.3'))
				? 'p:'.$this->hostname : $this->hostname;
			$port = empty($this->port) ? NULL : $this->port;
			$socket = NULL;
		}

		$client_flags = ($this->compress === TRUE) ? MYSQLI_CLIENT_COMPRESS : 0;
		$this->_mysqli = mysqli_init();

		$this->_mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 10);
        
        // ... 此处省略一些设置的代码
        
        if ($this->_mysqli->real_connect($hostname, $this->username, $this->password, $this->database, $port, $socket, $client_flags))
		{
			// Prior to version 5.7.3, MySQL silently downgrades to an unencrypted connection if SSL setup fails
			if (
				($client_flags & MYSQLI_CLIENT_SSL)
				&& version_compare($this->_mysqli->client_info, '5.7.3', '<=')
				&& empty($this->_mysqli->query("SHOW STATUS LIKE 'ssl_cipher'")->fetch_object()->Value)
			)
			{
				$this->_mysqli->close();
				$message = 'MySQLi was configured for an SSL connection, but got an unencrypted connection instead!';
				log_message('error', $message);
				return ($this->db->db_debug) ? $this->db->display_error($message, '', TRUE) : FALSE;
			}

			return $this->_mysqli;
		}

		return FALSE;
    }
}
  • 这里 mysqli_init 函数是 php 扩展自带的函数,返回的是 php 的 resource 类型的对象,即 mysqli 对象,这个对象可以用来查询数据库。

  • 再看下 CI_DB_query_builder 的部分实现,主要的功能是基于 driver 的方法,实现很多人性化的、可以链式调用的方法。

abstract class CI_DB_query_builder extends CI_DB_driver
{
    public function limit($value, $offset = 0)
	{
		is_null($value) OR $this->qb_limit = (int) $value;
		empty($offset) OR $this->qb_offset = (int) $offset;

		return $this;
	}
    
    public function offset($offset)
	{
		empty($offset) OR $this->qb_offset = (int) $offset;
		return $this;
	}
    
    public function get($table = '', $limit = NULL, $offset = NULL)
	{
		if ($table !== '')
		{
			$this->_track_aliases($table);
			$this->from($table);
		}

		if ( ! empty($limit))
		{
			$this->limit($limit, $offset);
		}

		$result = $this->query($this->_compile_select());
		$this->_reset_select();
		return $result;
	}
    
    function select() {}
    function distinct() {}
    function join() {}
    function from() {}
    function where() {}
    function or_where() {}
    function like() {}
    function group_by() {}
    function having() {}
    function update() {}
    
    // ...
}

原文链接:https://www.cnblogs.com/feiffy/p/codeignitor3-db-class.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:CodeIgnitor 3.0.x 之 db 类实现机制 - Python技术站

(0)
上一篇 2023年4月17日
下一篇 2023年4月17日

相关文章

  • PHP实现链式操作的核心思想

    PHP实现链式操作的核心思想是利用对象方法的返回值,使得多个方法可以链式调用。 首先,需要使用一个对象作为链式操作的起点,也就是对象方法的调用者。该对象通常被称为“链式对象”或“上下文对象”。 接着,在链式对象中实现方法,使它们可以返回自身的引用。这样,就可以把多个方法链式调用在一起。 例如,下面是一个使用链式操作的实现 Ajax 的示例: class Aj…

    PHP 2023年5月23日
    00
  • Lua编程示例(八):生产者-消费者问题

    Lua编程示例(八):生产者-消费者问题 一、生产者-消费者问题概述 生产者-消费者问题是指一个或多个生产者生成某种数据,一个或多个消费者消耗这些数据,而生成和消费的过程在同一时间却并不总是同步的。在多线程或并发编程中,这个问题常常出现。 这个问题可以用队列来模拟,当队列长度为0时,消费者等待数据的到达;当队列长度达到容量上限时,生产者等待队列中的数据被消费…

    PHP 2023年5月27日
    00
  • 十二个常见的PHP+MySql类免费CMS系统

    作为网站的作者,我将详细介绍“十二个常见的PHP+MySql类免费CMS系统”的攻略,下面将分为以下主要部分来介绍: 简介 安装步骤 常见问题 示例说明 简介 “十二个常见的PHP+MySql类免费CMS系统”是指在免费软件和开源软件中,广泛使用的12种基于 PHP + MySQL 技术构建的内容管理系统(CMS)。这些CMS系统结构简单、易于安装和维护,用…

    PHP 2023年5月23日
    00
  • php checkbox复选框值的获取与checkbox默认值输出方法

    当我们需要用户从多个选项中进行选择时,就可以使用复选框。PHP中获取复选框的值对于开发者来说非常重要。在本文中,我们将详细讲解如何使用PHP获取复选框的值并将默认值输出到HTML中。 获取复选框的值 要获取复选框的值,我们需要通过POST或GET方法将数据传递到PHP文件中。我们将使用HTML表单来演示。 HTML表单 <form action=&qu…

    PHP 2023年5月26日
    00
  • PHP实现根据数组的值进行分组的方法

    实现根据数组的值进行分组的方法,可以借助PHP自带的函数array_reduce()和array_merge()。具体步骤如下: 定义初始结果数组 通过array_reduce()函数对数组进行遍历,将结果放入一个初始化的空数组中。 $groups = array_reduce($arr, function($result, $item) { … ret…

    PHP 2023年5月26日
    00
  • PHP实现的简单sha1加密功能示例

    关于“PHP实现的简单sha1加密功能示例”的完整攻略,可以分为以下几个步骤: 1. 了解SHA1加密算法 SHA1是一种单向加密算法,就是说只能将原始的数据加密,但不能通过加密后的结果反推出原始的数据。SHA1算法可以将任意长度的数据(不限于文本)转换成固定长度的字符串(160位)。在实际中,SHA1广泛用于数据完整性校验、数字签名等安全应用。 2. PH…

    PHP 2023年5月26日
    00
  • php解析字符串里所有URL地址的方法

    解析字符串中的URL地址是在开发Web应用程序时经常面临的一个问题。PHP解析字符串中的所有URL地址可以使用正则表达式和PHP内置函数来完成。本文将为您提供一个完整的攻略,让您快速掌握这一技能。 步骤一:使用preg_match_all函数查找所有URL地址 在使用PHP解析字符串中的URL地址时,可以使用preg_match_all函数查找所有URL地址…

    PHP 2023年5月26日
    00
  • PHP生成HTML静态页面实例代码

    生成HTML静态页面是提高网站性能和解决一些兼容性问题的有效方式。在PHP中,可以使用代码生成静态页面,下面是PHP生成HTML静态页面的攻略。 步骤1:确定页面生成的逻辑 生成HTML静态页面需要有一个逻辑,例如用户访问特定的页面时,要调用哪些PHP脚本来生成HTML静态页面。这个逻辑可以根据实际情况和网站的需求来进行设计。 步骤2:使用ob_start函…

    PHP 2023年5月24日
    00
合作推广
合作推广
分享本页
返回顶部