2

我正在尝试在 MVC 框架中发送请求。我有一个将当前 URI 与定义的路由匹配的路由对象。如果匹配,则返回 Route 对象的实例。通过该 Route 对象,我可以访问匹配的控制器、方法和方法参数。

我可以这样使用它:

$route->getClass(); name of controller class to instantiate
$route->getMethod(); name of method to call
$route->getArgs(); array holding arguments that should be passed to method

如果需要,我还可以添加新参数。例如,我可以将依赖注入容器和当前 HTTP 请求对象实例添加到 args 中,如下所示:

$route->addArg('container', $container);
$route->addArg('request', $request);

现在 $route->getArgs 包含从 URI 获取的所有参数,还有一个 $container 实例和 $request 实例。$container 是我写的依赖注入容器。$request 是代表当前 HTTP 请求的对象。

所以想法是实例化路由器,获取当前路由,然后在每个方法/动作控制器中添加我想使用的对象。然后将该 Route 对象传递给 Dispatcher,当请求被分派时,我将能够在每个方法/动作控制器中使用 $container、$request 和其他参数。

我遇到的问题是,当我使用让我们说博客控制器和发布方法时。默认情况下,并且总是,它应该有 $container 和 $request 的实例(因为我将它们推送到 Route::$args 中,以及在路由定义中定义或从 URI 获取的任何其他参数/​​变量。

因此,当我在我的博客控制器中,发布方法时,我希望它的行为如下:

public function post($container, $request)
{
if($request->isAjax) {
// -- Its ajax request
}

$twig = $container->getService("Twig");
}

我发送请求是这样的:

我使用 call_user_function_array 使其工作:

$app = new $controller();
call_user_function_array(array($app, $method), $args);

现在这一切都可以正常工作,但我有一个问题。当我使用那个后控制器时,我必须小心后方法参数的顺序。

所以我可以这样做:

public function post($id, $url, $container, $request) {
// -- SNIP --
}

但我不能这样使用它:

public function post($container, $url, $request, $id) {
/-- SNIP --
}

所以你得到了问题,我不能按照我想要的方式在我的方法中混合参数,我需要注意这些参数在 Route:$args 数组中定义的顺序。

每个方法/动作控制器都应该有 $request 和 $container 实例以及通过 URI 获取或在路由定义中定义的参数。

有没有办法让它工作而不必考虑 post 方法获取参数的顺序是什么?这与通过引用传递有关吗?由于php按值传递变量?

我正在使用 call_user_function_array,我想找到 call_user_function_array 的解决方案。这可能吗?

如果没有,可以使用反射类来完成吗?

4

2 回答 2

2

这是我的问题的解决方案:

所以,我拥有发送请求所需的一切:

$class = "\\Application\\Controller\\Blog";
$method = "post";
$args = array('id' => 1, 'url' => 'some-url', 'container' => DICOBJ, 'request' => RQSTOBJ);

现在我需要发送该请求,以便用户可以按任何顺序插入参数,如果他愿意的话。

这是应该做的:

$app = new $class();

$rm = new \ReflectionMethod($app, $method);
$params = $rm->getParameters();

$argsOrdered = array();
foreach($params as $param) {
    $argsOrdered[$param->getName()] = $args[$param->getName()];
}

call_user_func_array(array($app, $method), $argsOrdered);

哒哒哒!!!

因此,它的作用是获取用户定义的参数,并按照用户编写它们的顺序将它们作为数组返回。然后我们创建另一个 $argsOrdered 数组,它只包含用户想要的参数,按照他想要的方式排序:)

我使用 ReflectionMethod 来检查方法。最后调用_user_func_array 来调度请求,但你也可以使用反射类来获取控制器实例。

而已。你觉得这个解决方案优雅吗?这可以更快地完成吗?

于 2012-10-19T21:23:39.283 回答
1

使用反射类,您可以获取要调用的函数的每个参数的参数名称,并以这种方式很容易地检查它们的顺序是否正确。你不能简单地用call_user_function_array.

特别是您可以getParameters() methodReflectionMethod 类中使用。

从那里开始,我认为您知道该怎么做(检查参数数组的每个键和传递的参数键,然后就可以了)。

于 2012-10-19T15:13:08.420 回答