__autoload:Escape ClassName

时间:2012-06-18 09:18:46

标签: php

这是我第一次尝试创建一个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 个答案:

答案 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。