Я пытаюсь отправить запрос в 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
Я также могу добавить новые аргументы, если мне нужно. Например, я могу добавить Contender Injection Contender и текущие экземпляры объекта HTTP-запроса в такие аргументы:
$route->addArg('container', $container); $route->addArg('request', $request);
Теперь $ route-> getArgs содержит все аргументы, полученные из URI, но также экземпляр $ container и экземпляр $ request. $ container – контейнер для инъекций зависимости, который я написал. И $ request – объект, представляющий текущий HTTP-запрос.
Поэтому идея состоит в том, чтобы создать экземпляр Router, получить текущий маршрут, а затем добавить объекты, которые я хотел бы использовать внутри каждого контроллера методов / действий. Затем передайте этот объект Route в Dispatcher, и когда будет отправлен запрос, я смогу использовать $ container, $ request и другие аргументы в каждом контроллере методов / действий.
У меня проблема в том, что когда я использую let, скажем, контроллер блога и метод post. По умолчанию и всегда, у него есть экземпляр $ container и $ request (поскольку я ввел их в Route :: $ args, плюс любой другой аргумент / переменную, определенную в определениях маршрутов или полученную из URI.
Поэтому, когда Im в моем блочном контроллере, почтовый метод, я хочу, чтобы он действовал следующим образом:
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);
Теперь все работает так, как должно, но у меня одна проблема. Когда я использую этот постконтроллер, я должен быть осторожным, в каком порядке упорядочены аргументы post method.
Поэтому я могу это сделать:
public function post($id, $url, $container, $request) { // -- SNIP -- }
но я не могу использовать его так:
public function post($container, $url, $request, $id) { /-- SNIP -- }
Таким образом, вы получаете проблему, я не могу смешивать аргументы внутри моего метода так, как я хочу, и мне нужно следить за порядком, в котором эти аргументы определяются в Route: $ args array.
Каждый контроллер методов / действий должен иметь $ request и $ container экземпляры плюс аргументы, полученные через URI или определенные в определении маршрута.
Есть ли способ заставить его работать, не думая, в каком порядке метод post получает аргументы? Связано ли это с передачей по ссылке? Поскольку php передает переменные по значению?
Я использую call_user_function_array, и я хочу найти решение для call_user_function_array. Это возможно?
Если нет, это можно сделать, используя класс Reflection?
С классом Reflection вы можете получить имена аргументов каждого параметра функции, которую вы хотите вызвать, и таким образом проверить, находятся ли они в правильном порядке очень легко. Вы не можете сделать это просто с помощью call_user_function_array
.
В частности, вы можете использовать метод getParameters() method
в классе ReflectionMethod .
Оттуда я думаю, что вы знаете, что делать (проверьте каждый ключ массива параметров с ключом переданного аргумента и там вы пойдете).
Это решение моей проблемы:
Итак, у меня есть все необходимое для отправки запроса:
$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);
Ta daaa !!!
Итак, что это делает, он получает определенные аргументы пользователем и возвращает их как массив, чтобы пользователь их написал. И тогда мы создаем еще один массив $ argsOrdered, который содержит только аргументы, которые хотят пользователи, заказанные так, как он хочет 🙂
Im использует ReflectionMethod для проверки метода. И в конце call_user_func_array для отправки запроса, но вы также можете использовать класс Reflection для получения экземпляра контроллера.
Это оно. Вы находите это решение элегантным? Можно ли это сделать быстрее?