controller.php
<?php
class CI_Controller { private static $instance; public function __construct()
{
self::$instance =& $this; foreach (is_loaded() as $var => $class)
{
$this->$var =& load_class($class);
$obj = $this->$var;
printf("var: |%s|, class: |%s|, obj: |%s|\n\n", $var, $class, var_export($obj, true));
}
} public static function &get_instance()
{
return self::$instance;
} public function get()
{
require 'model.php';
$model = new CI_Model();
$str = $model -> invoteClass();
return $str;
}
}
?>
model.php
<?php
class CI_Model {
public function __construct()
{
} /**
* 这个地方的__get魔术方法使用非常巧妙,值得研究一下
* 允许model层的类去访问对象$CI所指向的类中已经加载的类
*
* __get
*
* Allows models to access CI's loaded classes using the same
* syntax as controllers.
*
* @param string
* @access private
*/
public function __get($key)
{
$CI = &get_instance();
printf("inner %s\n\n", __METHOD__);
return $CI->$key;
} public function invoteClass()
{
//$this->appa调用魔术方法__get,魔术方法__get调用类CI_Controller中的成员变量appa
$obj = $this->appa;
echo 'inner ' . __METHOD__ . "\n\n";
printf("obj is: |%s|\n\n", var_export($obj, true));
printf("obj->getApp: %s\n\n", $obj->getApp()); $obj = $this->appb;
echo 'inner ' . __METHOD__ . "\n\n";
printf("obj is: |%s|\n\n", var_export($obj, true));
printf("obj->getApp: %s\n\n", $obj->getApp());
}
}
?>
common.php
<?php
if ( ! function_exists('load_class'))
{
function &load_class($class)
{
static $_classes = array(); // Does the class exist? If so, we're done...
// 如果要加载的类以前已经实例化过,则直接返回它
if (isset($_classes[$class]))
{
return $_classes[$class];
} if (file_exists($class.'.php'))
{
require($class.'.php');
} // Keep track of what we just loaded
//将所有加载过的类保存在静态数组_is_loaded中,
is_loaded($class); //实例化类$name(比如CI_Input),然后将实例化后的类保存在静态变量$_classes中,避免下次重复实例化
$_classes[$class] = new $class();
return $_classes[$class];
}
} // -------------------------------------------------------------------- /**
* Keeps track of which libraries have been loaded. This function is
* called by the load_class() function above
*
* @access public
* @return array
*/
if ( ! function_exists('is_loaded'))
{
function &is_loaded($class = '')
{
static $_is_loaded = array(); if ($class != '')
{
$_is_loaded[strtolower($class)] = $class;
} return $_is_loaded;
}
} function &get_instance()
{
return CI_Controller::get_instance();
}
?>
appa.php
<?php
class appA {
public function __construct() {
} public function getApp() {
return 'this is appa';
}
} ?>
appb.php
<?php
class appB {
public function __construct() {
} public function getApp() {
return 'this is appb';
}
}
?>
index.php
<?php
require 'controller.php';
require 'common.php'; load_class('appA');
load_class('appB');
$controller = new CI_Controller();
echo 'inner ' . __FILE__ . "\n\n";
$controller->get();
?>
运行php index.php输出结果如下:
E:\myphp\research\CodeIgniter_2.2.0\ci_study>php index.php
var: |appa|, class: |appA|, obj: |appA::__set_state(array(
))|
var: |appb|, class: |appB|, obj: |appB::__set_state(array(
))|
inner E:\myphp\research\CodeIgniter_2.2.0\ci_study\index.php
inner CI_Model::__get
inner CI_Model::invoteClass
obj is: |appA::__set_state(array(
))|
obj->getApp: this is appa
inner CI_Model::__get
inner CI_Model::invoteClass
obj is: |appB::__set_state(array(
))|
obj->getApp: this is appb
类CI_Model中并没有加载类appA与appB,确可以调用这两个类中的方法并取得数据,这里巧炒的采用了魔术方法__get的功能,并采用了单实例的设计模式实例了上述的调用过程,CI框架此处调用实在是巧炒,非常值得学习借鉴。