Я решил создать свою собственную мини — фреймворк для 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-подобного веб-сервиса, который должен быть масштабируемым и быстрым и обрабатывать десятки тысяч запросов в секунду, возможно).
Вы должны определить регулярные выражения для своих маршрутов и сопоставить их с запросами, если вы хотите знать, как 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
означает, что вы можете легко добавить свой собственный функционал в решение. Существующие преобразователи значений находятся здесь.