这是我第一次尝试创建一个frontController而且我遇到了一些小问题。
首先让我给你一个关于我的网站的样子:
当我在浏览器中打开http://mysite.com/test
时,服务器将使用GET参数$ controller(test)调用index.php。这是通过.htaccess完成的。
在index.php中,应该创建类$ controller的实例。
为此,我使用PHP的__autoload函数。
所以代码看起来像这样:
$controller = $_GET["controller"];
function __autoload($controller)
{
include("controllers/$controller.php");
if(!class_exists($controller, false))
{
eval
('
class '. $controller . '
{
public function __construct()
{
include("404.html");
exit();
}
}
');
}
}
$application = new $controller;
当您查看我提供的代码时,您可能已经注意到其中的 eval()。 当$ controller类不存在时,我使用它来避免致命错误,并显示404而不是它。
当有人输入像
这样的网址时,就开始了这个乐趣:会有
解析错误:语法错误,意外'!'
和...
致命错误:类'ImATroll!:D'未找到
所以问题是:我怎么能抓住这个?如何以一种只包含类名允许的字符的方式转义$ controller变量?
答案 0 :(得分:4)
我只是放弃 eval
部分,并在该部分直接重定向到404.
或者构建一个(非动态)404
- ContentNotFoundController,如果需要,只需使用/ yield(当类名不存在时)。
答案 1 :(得分:2)
为什么不在调用class_exists
之前尝试new $controller;
(class_exists会调用自动加载功能),如果为false,则包含('404.html');
function __autoload($classname){
$file = "controllers/$classname.php";
if(is_file($file))
include_once($file);
}
...但要注意安全问题 - 比如传入?controller = .. / htpasswd。您应该通过删除所有非字母数字字符来清理类名 - 例如$classname = preg_replace('/[^A-Za-z0-9]/', '', $classname);
答案 2 :(得分:1)
只需为找不到的类创建一个类:
if(!class_exists($controller, false))
{
$controller = "NotFound";
include("controllers/NotFoundController.php");
}
您还可以将允许的控制器列入白名单,并使用in_array()
检查您是否识别该类名称。这样做的缺点是你必须为你添加的每个课程改变白名单。
您还可以编写一个可以过滤可能的类名的正则表达式。
答案 3 :(得分:1)
实际上你可以从自动加载功能中抛出一个异常(p.s:代替使用spl_autoload_register)。
此异常是可捕获的,因此您可以提供“默认”功能。
这是迄今为止最好的方法,但如果你坚持创建这个假控制器,你应该使用class_alias。