1

这是我第一次尝试创建一个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 而不是它。

乐趣从这里开始:当有人输入一个类似的网址时

http://mysite.com/ImATroll!:D

将有

解析错误:语法错误,意外的“!”

和...

致命错误:找不到类 'ImATroll!:D'

所以问题是:我怎样才能抓住这个?如何以仅包含类名允许的字符的方式转义 $controller 变量?

4

4 回答 4

4

我会简单地删除eval部分并在该部分直接重定向到 404。

或者构建一个(非动态)404- ContentNotFoundController 如果你愿意,只需使用 / yield 那里(当类名不存在时)。

于 2012-06-18T09:22:58.030 回答
2

为什么不在class_exists调用之前尝试一下new $controller;(class_exists会调用autoload函数),如果为false,include('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);

于 2012-06-18T09:23:43.850 回答
1

只需为未找到的类创建一个类:

if(!class_exists($controller, false))
{
    $controller = "NotFound";
    include("controllers/NotFoundController.php");
}

您还可以将允许的控制器列入白名单,并检查in_array()您是否识别该类名称。这样做的缺点是您必须为添加的每个类更改白名单。

您还可以编写一个过滤可能的类名的正则表达式。

于 2012-06-18T09:26:39.343 回答
1

你实际上可以从你的自动加载函数中抛出一个异常(ps:使用spl_autoload_register代替)。

此异常是可捕获的,因此您可以提供“默认”功能。

这是迄今为止最好的方法,但如果你坚持创建这个假控制器,你应该使用 class_alias 代替。

于 2012-06-18T09:32:32.010 回答