zoukankan      html  css  js  c++  java
  • 一步一步重写 CodeIgniter 框架 (4) —— load_class 管理多个对象实例的思路

    我们使用CodeIgniter 框架最主要是想利用其 MVC 特性,将模型、视图分开,并通过控制器进行统一控制。在尝试实现 MVC 模式之前,我们将实现其中一个对程序结构非常有用的技巧,就是 load_class 函数。

    在上一课中,我们用面向对象的方法大大简化了程序的结构,将主要工作放在两个类中进行 ,URI 和 Router 类。 但是在 Router 类的构造函数中为了获得 uri 的实例,我们使用了 global 关键字,如下所示:

    1 class CI_Router {
    2     ...
    3     function __construct() {
    4         global $URI;
    5         $this->uri = &$URI;
    6     }
    7         ....
    8 }

    当程序的结构变得很复杂时,用 global 关键词会使得全局变量的管理非常乱,而且这些全局变量往往对应于一个具体功能类的实例,在实例化之前需要加载相应class的 php 文件。

    1. 问题提炼和分析

      根据上述分析,关键的问题是

      1)需要一个集成管理这些全局变量的地方

      2)这些类的实例产生时,很方便的加载对应的 php 文件。

      集成管理变量一般采用 类的方式,然后通过该类的一个实例(唯一一个)获取需要的变量,这个实例往往称为核心全局变量,如discuz 中的 $discuz_core 变量;

      另一种方式,就是函数,但是函数没法存储成员变量,所以必须利用一个很有用的语法特性,就是 static 静态变量。

      在这里,我们采用第二种更简洁的方式。

    2. 实现步骤

      1) 定义函数的接口

        函数名为 load_class , 我们希望通过传递一个字符串参数,就能获得对应的实例,比如 load_class('Router'); 就可以得到 上一课中的 $RTR 变量的引用。

        所以函数的接口为:    

    function &load_class($class) {}

      2) 定义存储这些重要类实例全局变量的静态数组 

    static $_classes = array();

    那么该数组,存储的键值对就是 ’Router' => $RTR  的样子。

      3) 具体的逻辑

     1 // 当加载需要的类实例时,如果不是第一次加载,那么 $_classes 数组中肯定存放了需要的实例,直接返回即可
     2     if (isset($_classes[$class])) {
     3         return $_classes[$class];
     4     }
     5 
     6     // 在我们的框架中,每个类实例都有前缀CI_
     7     $name = 'CI_'.$class;
     8 
     9     if (file_exists($class.'.php')) {
    10         require($class.'.php');
    11     } else {
    12         exit('Unable to locate the class');
    13     }
    14 
    15     $_classes[$class] = new $name();
    16     return $_classes[$class];

    3. 修改主逻辑代码  

     1 <?php
     2 /**
     3  * 框架主入口文件,所有的页面请求均定为到该页面,并根据 url 地址来确定调用合适的方法并显示输出
     4  */
     5 require('Common.php');
     6 
     7 $URI =& load_class('URI');
     8 $RTR =& load_class('Router');
     9 
    10 $RTR->set_routing();
    11 
    12 
    13 $class = $RTR->fetch_class();
    14 $method = $RTR->fetch_method();
    15 
    16 $CI = new $class();
    17 
    18 call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2));
    19 
    20 class Welcome {
    21 
    22     function hello() {
    23         echo 'My first Php Framework!';
    24     }
    25 
    26     function saysomething($str) {
    27         echo $str.", I'am the php framework you created!";
    28     }
    29 }

     另外,所有需要用到这些全局变量的地方,调用 load_class 就可以了,所以 Router 构造函数的地方使用 load_class.

    1 function __construct() {
    2     $this->uri =& load_class('URI');
    3 }

    4. 测试结果

      访问 http://localhost/learn-ci/index.php/welcome/hello , 可以看到输出为:

      hello, I'am the php framework you created!

  • 相关阅读:
    Android文字跑马灯控件(文本自动滚动控件)
    Android中的“再按一次返回键退出程序”实现
    Android中 在显示ImageView时图片上面和下面都出现一段空白区间的解决办法
    问题解决The connection to adb is down, and a severe error has occured.
    android关于uses-permission权限列表
    菜鸟学习Andriod-弹窗
    Andriod使用webview控件往APP里内嵌网页
    Mysql初始化root密码和允许远程访问
    转:Vmware Exsi使用简要说明
    转:怎样在VMware ESXi上 克隆虚拟机
  • 原文地址:https://www.cnblogs.com/zhenyu-whu/p/3183111.html
Copyright © 2011-2022 走看看