5

我正在尝试使用 php mvc,但遇到了以下问题。我的请求和路由器类非常简单,我想扩展主题以处理来自子文件夹的控制器调用,并且控制器类函数应该能够获取 url 变量发送它抛出 get 和 post。

我的路由器如下所示

class Router{

    public static function route(Request $request){


        $controller = $request->getController().'Controller';

        $method = $request->getMethod();

        $args = $request->getArgs();


        $controllerFile = __SITE_PATH.'/controllers/'.$controller.'.php';


        if(is_readable($controllerFile)){
            require_once $controllerFile;

            $controller = new $controller;


            if(!empty($args)){
                call_user_func_array(array($controller,$method),$args);
            }else{  
                call_user_func(array($controller,$method));
            }   
            return;
        }

        throw new Exception('404 - '.$request->getController().'--Controller not found');
    }
}

和请求类

    private $_controller;


    private $_method;

    private $_args;

    public function __construct(){

        $parts = explode('/',$_SERVER['REQUEST_URI']);


        $this->_controller = ($c = array_shift($parts))? $c: 'index';
        $this->_method = ($c = array_shift($parts))? $c: 'index';

        $this->_args = (isset($parts[0])) ? $parts : array();

    }

    public function getController(){

        return $this->_controller;

    }
    public function getMethod(){

        return $this->_method;

    }
    public function getArgs(){

        return $this->_args;
    }
}

问题是:当我尝试将抛出的 ajax 发送到控制器方法时,由于其 url 结构而无法识别该变量。例如

index/ajax?mod_title=shop+marks&domain=example

只要看起来就被接受

index/ajax/shop+mark/example
4

4 回答 4

10

您的代码包含所谓的LFI 漏洞,并且在当前状态下是危险的。
您应该将可以$controller用作/etc/passwd.

您的路由器使用不安全;谨防!

编辑:白名单示例

$safe = array(
    'ajax',
    'somecontroller',
    'foo',
    'bar',
);
if(!in_array($this->_controller, $safe))
{
    throw new Exception(); // replace me with your own error 404 stuff
}
于 2012-05-24T13:52:50.783 回答
2

由于您的请求类使用 URI 分段方法来识别控制器、操作和参数,因此您的请求中不会考虑 $_GET 或 $_REQUEST 等全局变量。

您需要做的是对您的请求代码进行一些补充。具体来说:

删除行:

$this->_args = (isset($parts[0])) ? $parts : array();

并添加以下内容:

$all_parts = (isset($parts[0])) ? $parts : array();
$all_parts['get'] = $_GET;
$this->_args = $all_parts;

这样,$_GET(即通过 url 传递的变量)变量将在调用的操作中可用,因为它们将在 $args 中(它们实际上将作为 $args['get'] 可用,这是保存的数组$_GET 变量,因此您可以使用 $args['get']['domain']) 访问 domain=example。

当然,您可以在 Request 类(例如查询)中再添加一种方法,如下所示:

public function query($var = null)
{
    if ($var === null)
    {
        return $_GET;
    }
    if ( ! isset($_GET[$var]) )
    {
        return FALSE;
    }
    return $_GET[$var];
}

这样,您可以从 url 中获取单个变量(例如 $request->query('domain'))或整个 $_GET 数组($request->query())。

于 2012-05-24T11:25:23.140 回答
0

那是因为 php 会自动将 "?mod_title=..." 放入$_GET数组中。您的getArgs()函数应检查$_GET,$_POST$_REQUEST.

如果您正在尝试使用最小的 MVC 方法,请查看 rasmus 的示例:http ://toys.lerdorf.com/archives/38-The-no-framework-PHP-MVC-framework.html

如果您的用例变得更复杂,请查看 Zend (http://framework.zend.com/manual/en/zend.controller.html) 或 Symfony (https://github.com/symfony /symfony/tree/master/src/Symfony/Component/Routing)做他们的事情。

于 2012-05-24T09:47:19.467 回答
0

选择任何流行的 MVC,看看他们是如何在后台实现它的。此外, spl_autoload_register 和 namespace 是你的朋友。

于 2013-10-24T09:44:34.247 回答