ThinkPHP源码分析系列—ADSL方法
为了提高编程效率和便于统一管理,ThinkPHP创建了一系列快捷方法,这些快捷方法均以单个的大写字母命名,这些字母往往是代表了函数用途的英文单词的首字母。 这些方法包括:A—快速实例化Action类函数 ,C— 存取配置参数值函数,D—快速实例化Model类函数,M—高效实例化Model类函数,L— 存取语言参数值函数,S—存取缓存函数,U—URL动态生成和重定向函数,等等。由于快捷方法里包含了ADSL,所以又称快捷方法为ADSL方法。
需要说明的是,ADSL方法中除G方法(记录和统计时间函数)外,其余方法都在系统函数库中定义,G方法在框架文件中定义,所以,一般情况下, ADSL方法都会被编译缓存到~runtime.php文件中,也就是说所有的ADSL方法都是全局可见 的,在任何地方都可以调用ADSL方法。
在ADSL方法中四种比较基本,并且在基于ThinkPHP框架开发应用中经常使用的是 C,D,M和U这四种方法,其中,U方法的实现和用法较复杂,将放在另一篇文章《ThinkPHP源码分析系列—ADSL方法之U方法》中单独介绍,这里仅介绍前三种方法,即:C 方法,D方法和M方法。
一,C方法
// 获取配置值 function C($name=null, $value=null) { static $_config = array(); // 无参数时获取所有 if (empty($name)) return $_config; // 优先执行设置获取或赋值 if (is_string($name)) { if (!strpos($name, '.')) { $name = strtolower($name); if (is_null($value)) return isset($_config[$name]) ? $_config[$name] : null; $_config[$name] = $value; return; } // 二维数组设置和获取支持 $name = explode('.', $name); $name[0] = strtolower($name[0]); if (is_null($value)) return isset($_config[$name[0]][$name[1]]) ? $_config[$name[0]][$name[1]] : null; $_config[$name[0]][$name[1]] = $value; return; } // 批量设置 if (is_array($name)) return $_config = array_merge($_config, array_change_key_case($name)); return null; // 避免非法参数 }
可以看到,C方法接受两个参数,默认都为空。当两个参数都为空时,返回所有通过该方法配置的值,函数通过一个静态数组来存储这些值。当第一个参数不为空且为字符串时,将分析参数的命名规则。 如果参数命名中 不 包含“.”,则对参数进行小写转换处理,并且在第二个参数不为空的情况下,将两个参数以键值对的形式存储在静态数组中,否则返回已配置 参数的值或空。如果参数命名中包含“.”,则将参数按“.”分割为数组,并且在第二个参数不为空的情况下,将两个参数以键值对的形式存储在静态数组(二维数组)中,否则返回已配置参数的值或空。当第一个参数不为空且为数组时,则将该数组键名转换为小写后加入到静态数组中,最后返回静态数组。其余情况,为了避免非法参数,返回空值。
知道了C方法的实现之后,使用C方法就简单了。通过给C方法传递参数, 如果该参数在配置文件中已设置, 则可以获取该参数的值。C方法支持获取二维数组的配置值,只需在配置文件中定义好数组格式,通过向C方法传递用“.”连接的参数即可。 当向C方法传递第二个参数时,C方法就在对参数进行动态配置,第一个参数为配置项名称,第二个参数为配置项值。C方法支持通过点语法(.)配置二维数组的值。
二,D方法
/** +---------------------------------------------------------- * D函数用于实例化Model +---------------------------------------------------------- * @param string name Model名称 * @param string app Model所在项目 +---------------------------------------------------------- * @return Model +---------------------------------------------------------- */ function D($name='', $app='') { static $_model = array(); if (empty($name)) return new Model; if (empty($app)) $app = C('DEFAULT_APP'); if (isset($_model[$app . $name])) return $_model[$app . $name]; $OriClassName = $name; if (strpos($name, '.')) { $array = explode('.', $name); $name = array_pop($array); $className = $name . 'Model'; import($app . '.Model.' . implode('.', $array) . '.' . $className); } else { $className = $name . 'Model'; import($app . '.Model.' . $className); } if (class_exists($className)) { $model = new $className(); } else { $model = new Model($name); } $_model[$app . $OriClassName] = $model; return $model; }
D方法用来实例化自定义业务逻辑的Model类。D方法包含两个参数,一个是模型类名称,一个是模型类所在项目,默认都为空。当系统找不到模型类时,会实例化基础模型类Model类,并返回实例化对象。当没有设置项目时,系统默认模型类在当前项目下。为了提高编程效率和代码重用性 ,D方法允许使用点语法(.)来实现跨项目实例模型类,默认是实例当前项目下模型类。ThinkPHP通过检查模型类名称的命名规则,分别去 加载不同的模型类。接着,判断是否存在这些模型类,如果存在则实例化该模型类,不存在则实例化基础模型类Model。值得一提的是,D方法中定义了一静态数组来存储已实例化的模型类,如果模型类已实例化,系统将不会重复去实例化,这样就减少了内存的使用,提高了 应用性能。
三,M方法
/** +---------------------------------------------------------- * M函数用于实例化一个没有模型文件的Model +---------------------------------------------------------- * @param string name Model名称 +---------------------------------------------------------- * @return Model +---------------------------------------------------------- */ function M($name='', $class='Model') { static $_model = array(); if (!isset($_model[$name . '_' . $class])) $_model[$name . '_' . $class] = new $class($name); return $_model[$name . '_' . $class]; }
M方法可看做D方法的一个特例。它将实例化一个没有模型文件的Model,即:没有定义自身业务逻辑,只能实现系统封装的CURD简单操作。当应用只是简单操作数据库时,使用M方法实例化对象是一种高效的选择。同样,M方法也不会去重复实例化模型类。
(完)