自定义MVC框架-自动加载类

栏目: 后端 · 发布时间: 7年前

内容简介:当前入口文件 index.php 中的代码在加载控制器类时手动拼写路径,然后再执行 require_once 加载控制器文件再观察其他文件中,凡是涉及到加载文件时,全部都是手动加载

当前入口文件 index.php 中的代码

//入口文件:程序的入口
$c = isset($_GET['c']) ? $_GET['c'] : 'home';
$a = isset($_GET['a']) ? $_GET['a'] : 'getNewsList';
//获取模块名称
$m = isset($_GET['m']) ? $_GET['m'] : 'home';
//常量是可以跨页面访问的
define("MODULE", $m);
$classname = $c . "Controller";
$actionname = $a . "Action";
//拼接的是控制器类所在的类文件的路径
$filename = "./application/" . $m . "/controller/" . $classname . ".class.php";
if (!file_exists($filename)) {
	echo "非法访问";
	die();
}
require_once $filename;
$controller_name = new $classname();
$controller_name->$actionname();

在加载控制器类时手动拼写路径,然后再执行 require_once 加载控制器文件

再观察其他文件中,凡是涉及到加载文件时,全部都是手动加载

缺点:如果被包含文件的路径或者名称发生变化,修改起来麻烦

解决方案:删除所有文件中的 require_once ,不再手动包含文件,采用自动加载机制

1. 设置命名空间

设置命名空间之后,自动加载函数执行时获取的就是带有命名空间前缀的名称,这个名称也指明了类的路径,在我们稍后测试时可以看到

1.1 示例:

控制器基类 Controller 命名空间为

namespace framework\core;

此类的代码中又用到了 Smarty,所以也引入了 Smarty类的命名空间

use \Smarty;

所以最后代码如下

namespace framework\core;
use \Smarty;

1.2 所有命名空间

下面以截图的方式列出所有类的命名空间及导入的命名空间

1.2.1 framework 目录下

自定义MVC框架-自动加载类

自定义MVC框架-自动加载类

自定义MVC框架-自动加载类

自定义MVC框架-自动加载类

1.2.2 admin 模块下的类

控制器类和模型类各选一个作为示例

自定义MVC框架-自动加载类

自定义MVC框架-自动加载类

1.2.3 home模块下的类

自定义MVC框架-自动加载类

自定义MVC框架-自动加载类

2. 重写入口文件

2.1 使用命名空间

自定义MVC框架-自动加载类

这是对原来的入口函数做了简单的修改,将 require_once 删除

注意 $classname 变量的值,拼接时分隔符使用的是“\”,而不是“/”,区别在于,前者是命名空间分隔符,后者只是路径分隔符,所以此变量的值其实是请求的控制器类的带有命名空间前缀的名称

例如,我们请求如下地址

http://localhost/news/index.php

则模块名称、控制器名称和方法名称都将使用默认值,即 home-home-getNewsList,则变量 classname 的值为

home\controller\homeController

这正好是HomeController类的带有命名空间的名称,因为HomeController 类的命名空间就是

home\controller

2.2 编写自动加载函数

在入口文件中编写如下函数,并注册为自动加载函数

function my_autoload($className){
    echo $className;
}
spl_autoload_register("my_autoload");

此时,入口文件的完整代码如下

//入口文件:程序的入口
//自动加载函数
function my_autoload($className){
    echo $className;
}
//注册自动加载函数
spl_autoload_register("my_autoload");

$c = isset($_GET['c']) ? $_GET['c'] : 'home';
$a = isset($_GET['a']) ? $_GET['a'] : 'getNewsList';
//获取模块名称
$m = isset($_GET['m']) ? $_GET['m'] : 'home';
//常量是可以跨页面访问的
define("MODULE", $m);
$classname = MODULE . "\\controller\\" . $c . "Controller";
$actionname = $a . "Action";
$c = new $classname();
$c->$actionname();

访问入口文件,输出如下

自定义MVC框架-自动加载类

然后就可以写代码将其包含进来

function my_autoload($className){
    echo $className."<br>";
    require_once "./application/".$className.".class.php";
}

再次运行入口文件

自定义MVC框架-自动加载类

错误在于,执行 HomeController 类时,其中还导入了其他命名空间的类

自定义MVC框架-自动加载类

自动加载函数会自动加载此类所在的文件,所以会将参数 className 的值赋值给 framework/core/Controller

而在自动载入函数中又有如下代码

require_once "./application/".$className.".class.php";

所以会导致去错误的路径寻找文件

解决方法:加载文件时要分门别类,根据文件所在的目录判断

有些类的命名空间以 “framework” 开头,如上面 Controller类的命名空间"framework/core",有些类的命名空间则以模块名称开头,application 中的所有类都时这样

所以修改代码如下

function my_autoload($className){
    //将类名按照“\”分割成数组
    $ary=explode("\\",$className);
    if ($ary[0]=="framework"){
        $baseDir="./";
    }else{
        $baseDir="./application/";
    }
    $filename=$baseDir.$className.".class.php";
    echo $filename."<br>";
    require_once $filename;
}

运行结果如下

自定义MVC框架-自动加载类

在加载 smarty 类时出现错误,路径又不对了

所以Smarty 要特殊对待

function my_autoload($className){
    //smarty类特殊对待
    if ($className=="Smarty"){
        require_once './framework/vender/smarty/Smarty.class.php';
        return;
    }
    //将类名按照“\”分割成数组
    $ary=explode("\\",$className);
    if ($ary[0]=="framework"){
        $baseDir="./";
    }else{
        $baseDir="./application/";
    }
    $filename=$baseDir.$className.".class.php";
    echo $filename."<br>";
    require_once $filename;
}

再次运行

自定义MVC框架-自动加载类

原因在于 Smarty_Autoloader.class.php 是Smarty 包中的文件,会自动加载,不需要在我们的自动载入函数中加载

自定义MVC框架-自动加载类

再次运行

自定义MVC框架-自动加载类

错误在于,i_DAO 是一个接口,名称不是 i_DAL.class.php ,而是 i_DAL.interface.php

所以再次修改代码

function my_autoload($className){
    if ($className=="Smarty_Autoloader"){
        return;
    }
    //smarty类特殊对待
    if ($className=="Smarty"){
        require_once './framework/vender/smarty/Smarty.class.php';
        return;
    }
    //将类名按照“\”分割成数组
    $ary=explode("\\",$className);
    if ($ary[0]=="framework"){
        $baseDir="./";
    }else{
        $baseDir="./application/";
    }
    //判断后缀名
    if (strpos($className,"i_")){
        $fix=".interface.php";
    }else{
        $fix=".class.php";
    }
    $filename=$baseDir.$className.$fix;
    echo $filename."<br>";
    require_once $filename;
}

搞定!


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Hacking

Hacking

Jon Erickson / No Starch Press / 2008-2-4 / USD 49.95

While other books merely show how to run existing exploits, Hacking: The Art of Exploitation broke ground as the first book to explain how hacking and software exploits work and how readers could deve......一起来看看 《Hacking》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换