PHP - call_user_function_array или класс Reflection передаются по ссылке?

76
9

Я пытаюсь отправить запрос в среду 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, получить текущий маршрут, а затем добавить объекты, которые я хотел бы использовать внутри каждого метода /action controller. И затем передайте этот объект Route в Dispatcher, и когда запрос будет отправлен, я смогу использовать $container, $request и другие аргументы в каждом контроллере методов/действий.


Проблема заключается в том, что когда я использую let, скажем, контроллер блога и метод post. По умолчанию и всегда, у него есть экземпляр $container и $request (поскольку я ввел их в Route:: $args, плюс любой другой аргумент/переменную, определенную в определениях маршрутов или полученную из URI.


Итак, когда Im в моем блочном контроллере, метод post, я хочу, чтобы он работал следующим образом:


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?

спросил(а) 2021-01-19T09:29:11+03:00 2 месяца, 4 недели назад
1
Решение
75

Это решение моей проблемы:


Итак, у меня есть все необходимое для отправки запроса:


$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 для получения экземпляра контроллера.


Вот оно. Вы находите это решение элегантным? Можно ли это сделать быстрее?

ответил(а) 2021-01-19T09:29:11+03:00 2 месяца, 4 недели назад
62

С классом Reflection вы можете получить имена аргументов каждого параметра функции, которую вы хотите вызвать, и таким образом проверить, находятся ли они в правильном порядке очень легко.
Вы не можете сделать это просто с помощью call_user_function_array.


В частности, вы можете использовать getParameters() method в классе ReflectionMethod.

Оттуда я думаю, что вы знаете, что делать (проверьте каждый ключ массива параметров с ключом переданного аргумента и там вы идете).

ответил(а) 2021-01-19T09:29:11+03:00 2 месяца, 4 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема