我正在尝试在 MVC 框架中分派(dispatch)请求。 我有一个路由对象,它将当前 URI 与定义的路由进行匹配。如果存在匹配,则返回 Route 对象的实例。通过该 Route 对象,我可以访问匹配的 Controller 、方法和方法参数。
我可以这样使用它:
$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
如果需要,我还可以添加新参数。例如,我可以将依赖注入(inject)容器和当前 HTTP 请求对象实例添加到 args,如下所示:
$route->addArg('container', $container);
$route->addArg('request', $request);
现在 $route->getArgs 保存从 URI 获取的所有参数,还有 $container 实例和 $request 实例。 $container 是我写的依赖注入(inject)容器。 $request是代表当前HTTP请求的对象。
所以我们的想法是实例化 Router,获取当前 Route,然后添加我想在每个方法/ Action Controller 中使用的对象。然后将该 Route 对象传递给 Dispatcher,当调度请求时,我将能够在每个方法/操作 Controller 中使用 $container、$request 和其他参数。
我遇到的问题是,当我使用博客 Controller 和发布方法时。默认情况下,并且始终,它应该具有 $container 和 $request 的实例(因为我将它们插入 Route::$args,以及路由定义中定义或从 URI 获取的任何其他参数/变量。
所以当我在我的博客 Controller 中时,发布方法我希望它的行为如下:
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);
现在一切都正常了,但我有一个问题。 当我使用该后置 Controller 时,我必须小心后置方法参数的排序顺序。
所以我可以这样做:
public function post($id, $url, $container, $request) {
// -- SNIP --
}
但我不能这样使用它:
public function post($container, $url, $request, $id) {
/-- SNIP --
}
所以你遇到了问题,我无法按照我想要的方式在方法中混合参数,并且我需要密切关注这些参数在 Route:$args 数组中定义的顺序。
每个方法/操作 Controller 都应该有 $request 和 $container 实例以及通过 URI 获取或在路由定义中定义的参数。
有没有办法让它工作而不必考虑post方法获取参数的顺序?这与引用传递有关系吗?既然php按值传递变量?
我正在使用 call_user_function_array,我想找到 call_user_function_array 的解决方案。 这可能吗?
如果没有,可以使用 Reflection 类来完成吗?
最佳答案
这是我的问题的解决方案:
所以,我拥有发送请求所需的一切:
$class = "\\Application\\Controller\\Blog";
$method = "post";
$args = array('id' => 1, 'url' => 'some-url', 'container' => DICOBJ, 'request' => RQSTOBJ);
现在我需要分派(dispatch)该请求,以便用户可以根据需要以任何顺序插入参数。
这是应该做的:
$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来调度请求,但您也可以使用Reflection类来获取 Controller 实例。
就是这样。您觉得这个解决方案优雅吗?这可以更快地完成吗?
关于PHP - call_user_function_array 或 Reflection 类通过引用传递?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12976855/