说明:没特别指明的情况下,本文涉及的Codeigniter均为3.1.2版。
要在 CI 框架里使用数据库,你可以显示地加载它:
$this->load->database(db_to_load);
也可以在加载 model 的时候顺带加载数据库:
// 第三个参数
$this->load->model(model_to_load, name, db_to_load);
当我们只有一个数据库的时候,上面两种方法都行得通。默认情况下,CI 把数据库连接赋值给一个叫 db 的属性。但如果有多个数据库(>=2),并且要经常切换,就只能使用 database()
并且第二个参数传 true,例如:
$this->dblink = $this->load->database(db_to_load, true);//return ?
我们看一下 database()
方法的部分实现细节:
// database() 方法开头会判断 db 是否已被赋值
if ($return === FALSE && $query_builder === NULL && isset($CI->db) && is_object($CI->db) && ! empty($CI->db->conn_id))
{
return FALSE;
}
...
// 返回数据库连接
if ($return === TRUE)
{
return DB($params, $query_builder);
}
...
// 赋值给 db
$CI->db =& DB($params, $query_builder);
看得出来,每次执行 database(db_to_load, true) 的时候都会连接一次数据库,所以在必要时才 load model。
注:1. 上面指的是调用 database(db_to_load, true);不是 database(db_to_load);
2. 读者事先看过 DB() 方法,知道 DB() 会去连数据库 o( ̄▽ ̄)o 。
下面是 DB()
方法的部分实现细节:
...
//此处有很多 include 和 require_once
...
// $params['dbdriver'] 在配置数据库时指定,比如 mysql
$driver = 'CI_DB_'.$params['dbdriver'].'_driver';
$DB = new $driver($params);
...
// $driver 继承的某个抽象类有 initialize() 方法
$DB->initialize();
下面是 initialize()
方法的部分实现细节:
//这是 CI_DB_driver 类
if ($this->conn_id)
{
return TRUE;
}
// db_connect 由继承该类的派生类实现
$this->conn_id = $this->db_connect($this->pconnect);
...
// 最后设置mysql(客户端)编码
return $this->db_set_charset($this->char_set);
如果你再深入源码了解 CI_DB_driver 类,你会发现下面的关系链:
$driver extends CI_DB { } // drivers 举例: CI_DB_mysql_driver
class CI_DB extends CI_DB_query_builder { } // CI_DB 是个空类
// or: class CI_DB extends CI_DB_driver { }
abstract class CI_DB_query_builder extends CI_DB_driver { }
abstract class CI_DB_driver { }
上面出现了两个抽象类,它们一个偏向于 Query,一个偏向于 DB,下面是两个类的注释:
CI_DB_query_builder : This is the platform-independent base Query Builder implementation class.
CI_DB_driver: This is the platform-independent base DB implementation class.
CI_DB
是个空类,没有任何实现,但是所有数据库驱动类(例如 CI_DB_mysql_driver
)都继承 CI_DB
。
注意到 &DB(params, query_builder_override)
方法的第二个参数,它决定了 CI_DB
继承 CI_DB_query_builder
还是 CI_DB_driver
:
if (! isset($query_builder) OR $query_builder === TRUE)
{
if ( ! class_exists('CI_DB', FALSE))
{
class CI_DB extends CI_DB_query_builder { }
}
}
elseif ( ! class_exists('CI_DB', FALSE))
{
class CI_DB extends CI_DB_driver { }
}
可以看出来,CI_DB
起到了“适配器”的作用。
完。