M方法是TP中最多见的一个模型化没有文件的Model方法。仔细进行解析的时候,会发现里面逻辑也是挺多的,这节主要梳理TP框架最多见的M方法。
方法代码:
function M($name='', $tablePrefix='',$connection='') {
//设立一个静态变量,能够在运行过程当中,一直保存的值
static $_model = array();
//若是在里面找到了:号,就用explode进行分割提取,不然就读取model
if(strpos($name,':')) {
//M方法实例化的时候,默认状况下是直接实例化系统的\Think\Model类,
//示例M('\Home\Model\CommonModel:User','think_','db_config');这种通常用的比较少,大多数状况下用Think\\Model
list($class,$name) = explode(':',$name);
}else{
// 默认的class就是
$class = 'Think\\Model';
}
//链接标记数组标记
$guid = (is_array($connection)?implode('',$connection):$connection).$tablePrefix . $name . '_' . $class;
//没有模型化将缓存里面的对象返回出来
if (!isset($_model[$guid]))
$_model[$guid] = new $class($name,$tablePrefix,$connection);
return $_model[$guid];
}
运行逻辑:检测是否是实例化默认的类,将其放入一个$_model数组中,并给每一个实例化都赋予一个键值。
默认执行的类是:
$a = new \Think\Model();
实例化的时候__construct()
public function __construct($name='',$tablePrefix='',$connection='') {
//在自动加载的时候,实现自动初始化,能够加入用户本身的断定逻辑
$this->_initialize();
if(!empty($name)) {
if(strpos($name,'.')) {
// 支持 数据库名.模型名的 定义
list($this->dbName,$this->name) = explode('.',$name);
}else{
$this->name = $name;
}
}elseif(empty($this->name)){
$this->name = $this->getModelName();
}
// 设置表前缀
if(is_null($tablePrefix)) {// 前缀为Null表示没有前缀
$this->tablePrefix = '';
}elseif('' != $tablePrefix) {
$this->tablePrefix = $tablePrefix;
}elseif(!isset($this->tablePrefix)){
$this->tablePrefix = C('DB_PREFIX');
}
// 数据库初始化操做
// 获取数据库操做对象
// 当前模型有独立的数据库链接信息
$this->db(0,empty($this->connection)?$connection:$this->connection,true);
}
自动加载运行逻辑:初始化模型,将输入的字段储存到$this->name和$this->db,而后读取链接信息
默认的数据库链接,数据库的链接配置
public function db($linkNum='',$config='',$force=false) {
if('' === $linkNum && $this->db) {
return $this->db;
}
static $_db = array();
if(!isset($_db[$linkNum]) || $force ) {
// 建立一个新的实例
if(!empty($config) && is_string($config) && false === strpos($config,'/')) { // 支持读取配置参数
$config = C($config);
}
$_db[$linkNum] = Db::getInstance($config);
}elseif(NULL === $config){
$_db[$linkNum]->close(); // 关闭数据库链接
unset($_db[$linkNum]);
return ;
}
// 切换数据库链接
$this->db = $_db[$linkNum];
$this->_after_db();
// 字段检测,能够经过DB_FIELDS_CACHE控制是否缓存数据库的字段(常常变更字段的,应该禁止掉该参数)
if(!empty($this->name) && $this->autoCheckFields) $this->_checkTableInfo();
return $this;
}
运行逻辑:建立一个配置,切换数据库链接,每次都读取配置里面的配置信息进行实例化变更
获取数据库的实例:
public static function getInstance($db_config='') {
static $_instance = array();
//生成一个惟一的键值,用储存
$guid = to_guid_string($db_config);
if(!isset($_instance[$guid])){
$obj = new Db();
$_instance[$guid] = $obj->factory($db_config);
}
return $_instance[$guid];
}
加载驱动进行控制:
public function factory($db_config='') {
// 读取数据库配置
$db_config = $this->parseConfig($db_config);
if(empty($db_config['dbms']))
E(L('_NO_DB_CONFIG_'));
// 数据库类型
if(strpos($db_config['dbms'],'\\')){
$class = $db_config['dbms'];
}else{
$dbType = ucwords(strtolower($db_config['dbms']));
$class = 'Think\\Db\\Driver\\'. $dbType;
}
// 检查驱动类
if(class_exists($class)) {
$db = new $class($db_config);
}else {
// 类没有定义
E(L('_NO_DB_DRIVER_').': ' . $class);
}
return $db;
}
运行逻辑:根据配置读取对应的数据库控制驱动(经常使用的mysql或者mysqli驱动等)
整理后M的运行逻辑流程以下:(M('user')流程)
实例化model-》自动加载实现(获取到name,dbname,db等)——》$this->db根据当前配置去实例化对应的Db类
——》Db类里根据当前的配置去找到对应的数据库驱动,同时进行实例化返回——》返回$this,进行其余的操做
M的几种用法展现:
1.$Model = M();
//进行原生的SQL查询
$Model->query('SELECT * FROM think_user WHERE status = 1');
2.M('\Home\Model\CommonModel:User','think_','db_config');mysql