Создание собственного обработчика аргументов для моей собственной PHP-фреймворка
Я решил создать свою собственную мини - фреймворк для PHP, которую я собираюсь использовать для реальной работы, создание веб-сервиса для социального приложения.
Я начал с руководства Фабьена Потенсьера по созданию вашей собственной платформы поверх компонентов Symfony - http://symfony.com/doc/current/create_framework/index.html. Мне очень понравились его библиотеки classLoader и http-foundation и я решил их интегрировать.
Я прочитал весь учебник, но решил прекратить интеграцию компонентов Symfony до пятой части учебника, где он попадает в ядро Symfony http, средство сопоставления маршрутов и преобразователь контроллеров (исключая те).
Есть вопрос о фронт-контроллере и картографическом маршруте моего фреймворка, о котором идет речь.
front.php (фронт-контроллер)
<?php
require 'config/config.php';
require 'config/routing.php';
require 'src/autoloader.php';
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
$request = Request::createFromGlobals();
$response = new Response();
$path = $request->getPathInfo();
if(isset($siteMap[$path])) {
call_user_func_array('src\Controllers' .'\\' . $siteMap[$path]['controller'] . '::' . $siteMap[$path]['action'], array($siteMap[$path]['arguments']));
} else {
$response->setStatusCode('404');
$response->setContent('Page not found');
}
$response->send();
?>
Мой файл маршрутизации:
/*
Map of routes
*/
$siteMap = array('/' => array('controller' => 'IndexController', 'action' => 'indexAction', 'arguments' => ''),
'/categories' => array('controller' => 'CategoriesController', 'action' => 'indexAction', '
То, что я хочу знать сейчас, это без дальнейшего использования компонентов Symfony, как я могу сделать что-то вроде этого:
В моем файле маршрутизации я хочу добавить URL-адрес, например '/hello', с Controller - Hello Controller и именем аргумента, возрастом, полом, который будет соответствовать запросу в браузере GET www.base/hello/samuel/11/male.
А в HelloController есть indexAction($name, $age, $ sex) { ... }. Я попытался посмотреть на исходные тексты Symfony, но до сих пор это ускользает от меня (я провел много времени, изучая исходный код библиотек). Я собираюсь модульно разделить функции переднего контроллера и контроллера, решая их еще дальше, но я хочу разобраться в этом.
Ну, а также любые советы по дальнейшему построению моей инфраструктуры (я бы создал инфраструктуру для REST -подобного веб-сервиса, который должен быть масштабируемым и быстрым и, возможно, обрабатывать десятки тысяч запросов в секунду).
2 ответа
Вы должны определить регулярные выражения для своих маршрутов и сопоставить их с запросами, если вы хотите знать, как Symfony преобразует свой собственный формат маршрута, например: '/path/to/{id}' в регулярное выражение, см. RouteCompiler:: compilePattern. Это выходит за рамки этого вопроса, и я не предоставлю никакого кода для него.
Регулярное выражение для вашего примера маршрута будет что-то вроде ^/hello/(\w*)/(\d*)/(\w*)/$
, это будет соответствовать '/ привет / любая строка / любое число / любая строка /' например: /hello/samuel/11/male
(не забудьте ^
и $
они соответствуют началу и концу строки).
Вы должны предоставить регулярное выражение для каждого маршрута и сделать preg_match(rawurldecode($request->getPathInfo(), $regex /* as created earlier*/, $matches)
против всех маршрутов (до совпадения) вместо isset($sitemap[$path])
если это возвращает false, маршрут не совпадает. в противном случае вы должны получить аргументы для вашего контроллера следующим образом:
preg_match(rawurldecode($request->getPathInfo(), $regex /* as created earlier*/, $matches)
$args = array();
// we omit the first element of $matches, since it's the full string for the match
for($i = 1; $i < count($matches); $i++){
$args[] = $matches[$i];
}
Теперь вы можете объединить $args
с аргументами по умолчанию и вызвать контроллер.
См. UrlMatcher:: matchCollection () о том, как Symfony сопоставляет каждый маршрут с регулярным выражением, и создает аргументы.
Я хотел бы добавить дополнительную информацию. В Symfony вы можете получить Аргументы вашего запроса в аргументы метода:
public function fooAction($bar);
В этом случае это будет выглядеть в $request->attributes
за ключ с bar
, если значение присутствует, оно добавит это значение в ваше действие. В Symfony 3.0 и ниже это делается через ControllerResolver::getArguments()
, Начиная с Symfony 3.1 вы сможете реализовать или расширить ArgumentResolver
,
Используя ArgumentResolver
означает, что вы можете легко добавить свой собственный функционал в решение. Существующие преобразователи значений находятся здесь.