CI框架中一个类中调用另一个类中已经加载对象测试

时间:2022-05-09 20:03:59

controller.php

 1 <?php
 2 class CI_Controller {
 3 
 4     private static $instance;
 5 
 6     public function __construct()
 7     {
 8         self::$instance =& $this;
 9 
10         foreach (is_loaded() as $var => $class)
11         {
12             $this->$var =& load_class($class);
13             $obj = $this->$var;
14             printf("var: |%s|, class: |%s|, obj: |%s|\n\n", $var, $class, var_export($obj, true));
15         }
16     }
17 
18     public static function &get_instance()
19     {
20         return self::$instance;
21     }
22 
23     public function get()
24     {
25         require 'model.php';
26         $model = new CI_Model();
27         $str = $model -> invoteClass();
28         return $str;
29     }
30 }
31 ?>

 model.php

 1 <?php
 2 class CI_Model {
 3     public function __construct()
 4     {
 5     }
 6 
 7     /**
 8      * 这个地方的__get魔术方法使用非常巧妙,值得研究一下
 9      * 允许model层的类去访问对象$CI所指向的类中已经加载的类
10      *
11      * __get
12      *
13      * Allows models to access CI's loaded classes using the same
14      * syntax as controllers.
15      *
16      * @param   string
17      * @access private
18      */
19     public function __get($key)
20     {
21         $CI = &get_instance();
22         printf("inner %s\n\n", __METHOD__);
23         return $CI->$key;
24     }
25 
26     public function invoteClass()
27     {
28         //$this->appa调用魔术方法__get,魔术方法__get调用类CI_Controller中的成员变量appa
29         $obj = $this->appa;
30         echo 'inner ' . __METHOD__ . "\n\n";
31         printf("obj is: |%s|\n\n", var_export($obj, true));
32         printf("obj->getApp: %s\n\n", $obj->getApp());
33 
34         $obj = $this->appb;
35         echo 'inner ' . __METHOD__ . "\n\n";
36         printf("obj is: |%s|\n\n", var_export($obj, true));
37         printf("obj->getApp: %s\n\n", $obj->getApp());
38     }
39 }
40 ?>

common.php

 1 <?php
 2 if ( ! function_exists('load_class'))
 3 {
 4     function &load_class($class)
 5     {
 6         static $_classes = array();
 7 
 8         // Does the class exist?  If so, we're done...
 9         // 如果要加载的类以前已经实例化过,则直接返回它
10         if (isset($_classes[$class]))
11         {
12             return $_classes[$class];
13         }
14 
15         if (file_exists($class.'.php'))
16         {
17             require($class.'.php');
18         }
19 
20         // Keep track of what we just loaded
21         //将所有加载过的类保存在静态数组_is_loaded中,
22         is_loaded($class);
23 
24         //实例化类$name(比如CI_Input),然后将实例化后的类保存在静态变量$_classes中,避免下次重复实例化
25         $_classes[$class] = new $class();
26         return $_classes[$class];
27     }
28 }
29 
30 // --------------------------------------------------------------------
31 
32 /**
33 * Keeps track of which libraries have been loaded.  This function is
34 * called by the load_class() function above
35 *
36 * @access   public
37 * @return   array
38 */
39 if ( ! function_exists('is_loaded'))
40 {
41     function &is_loaded($class = '')
42     {
43         static $_is_loaded = array();
44 
45         if ($class != '')
46         {
47             $_is_loaded[strtolower($class)] = $class;
48         }
49 
50         return $_is_loaded;
51     }
52 }
53 
54 function &get_instance()
55 {
56     return CI_Controller::get_instance();
57 }
58 ?>

appa.php

 1 <?php
 2 class appA {
 3     public function __construct() {
 4     }
 5 
 6     public function getApp() {
 7         return 'this is appa';
 8     }
 9 }
10 
11 ?>

appb.php

 1 <?php
 2 class appB {
 3     public function __construct() {
 4     }
 5 
 6     public function getApp() {
 7         return 'this is appb';
 8     }
 9 }
10 ?>

index.php

 1 <?php
 2 require 'controller.php';
 3 require 'common.php';
 4 
 5 load_class('appA');
 6 load_class('appB');
 7 $controller = new CI_Controller();
 8 echo 'inner ' . __FILE__ . "\n\n";
 9 $controller->get();
10 ?>

运行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框架此处调用实在是巧炒,非常值得学习借鉴。