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

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

内容简介:当前入口文件 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;
}

搞定!


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

查看所有标签

猜你喜欢:

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

千夫所指

千夫所指

乔恩·罗森 / 王岑卉 / 九州出版社 / 2016-10-1 / CNY 42.80

编辑推荐: 《乌合之众》是为了跪舔权贵?《普通心理学》实验存在重大漏洞?《引爆点》的理论都是瞎掰的?社交网络时代《1984》预言的“老大哥”是否已经变成事实? 《纽约时报》年度十佳书 《GQ》杂志年度十佳书 《卫报》年度十佳书 《泰晤士报》年度十佳书 《经济学人》年度重推! 黑天鹅年度重点图书! 《乌合之众》是为了迎合权贵?《普通心理学》实验存在重大......一起来看看 《千夫所指》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

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

UNIX 时间戳转换

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具