Ответ 1
Как рамки и библиотеки интерпретируют обязанности маршрутизатора и диспетчера, будут отличаться. Ниже я подробно описываю, как I интерпретировать обязанности этих двух служб. Нельзя сказать, что это единственный способ интерпретировать его или что другие интерпретации ошибочны.
Концепции
Routing
Это похоже на прохождение маршрутов на бензоколонке или в магазине. Вы проходите через город, и вам нужно выяснить, как добраться до ближайшего отеля. Вы заходите и спрашиваете у сопровождающего, и они указывают вас в правильном направлении, или, по крайней мере, вы надеетесь, что направления верны. Маршрутизация - это именно так. Запрос поступает на ресурс, Маршрутизатор предоставляет указания, необходимые для запроса для получения правильного ресурса.
В большинстве основных платформ вы собираетесь маршрутизировать определенный URL-адрес запроса на объект и метод, которые будут вызываться для завершения запроса. Часто вы увидите, что маршрутизатор также анализирует динамические аргументы из URL. Например, если вы обращались к пользователям через /users/1234
, где 1234
- это идентификатор пользователя, маршрутизатор будет анализировать часть идентификатора и предоставлять это как часть указаний на ресурс.
Диспетчерская
Dispatching использует информацию с шага маршрутизации для фактического создания ресурса. Если шаг маршрутизации запрашивает указания, Dispatching - это фактический процесс следования этим направлениям. Dispatching точно знает, что нужно создавать, и шаги, необходимые для создания ресурса, но только после получения маршрутов от маршрутизатора.
Реализации
Эти примеры реализации преднамеренно очень просты и наивны. Вы не хотели бы использовать это в какой-либо производственной среде без резких улучшений.
В этом примере вместо маршрутизации к объекту и методу мы просто перейдем к вызываемой функции. Это также демонстрирует, что вам не нужно направлять объект; до тех пор, пока диспетчер может правильно получить правильный ресурс, вы можете маршрутизировать любые нужные вам данные.
Сначала нам нужно что-то проложить. Позвольте создать простой объект Request, с которым мы можем сопоставлять.
<?php
class Request {
private $method;
private $path;
function __construct($method, $path) {
$this->method = $method;
$this->path = $path;
}
function getMethod() {
return $this->method;
}
function getPath() {
return $this->path;
}
}
Теперь, когда мы можем сопоставить что-то, взглянем на простую реализацию маршрутизатора.
<?php
class Router {
private $routes = [
'get' => [],
'post' => []
];
function get($pattern, callable $handler) {
$this->routes['get'][$pattern] = $handler;
return $this;
}
function post($pattern, callable $handler) {
$this->routes['post'][$pattern] = $handler;
return $this;
}
function match(Request $request) {
$method = strtolower($request->getMethod());
if (!isset($this->routes[$method])) {
return false;
}
$path = $request->getPath();
foreach ($this->routes[$method] as $pattern => $handler) {
if ($pattern === $path) {
return $handler;
}
}
return false;
}
}
И теперь нам нужно каким-то образом вызвать сконфигурированный $handler
для данного запроса.
<?php
class Dispatcher {
private $router;
function __construct(Router $router) {
$this->router = $router;
}
function handle(Request $request) {
$handler = $this->router->match($request);
if (!$handler) {
echo "Could not find your resource!\n";
return;
}
$handler();
}
}
Теперь давайте объединим все вместе и покажем, как использовать эти простые реализации.
<?php
$router = new Router();
$router->get('foo', function() { echo "GET foo\n"; });
$router->post('bar', function() { echo "POST bar\n"; });
$dispatcher = new Dispatcher($router);
$dispatcher->handle(new Request('GET', 'foo'));
$dispatcher->handle(new Request('POST', 'bar'));
$dispatcher->handle(new Request('GET', 'qux'));
Вы можете увидеть пример этой реализации в действии, проверив http://3v4l.org/gbsoJ.
Обтекание
В этом примере реализации предполагается передать концепцию маршрутизации и диспетчеризации. Действительно, для выполнения этих действий намного больше, чем в моем примере. Часто маршрутизатор будет использовать регулярное выражение для сопоставления с запросом и может искать другие атрибуты запроса при сопоставлении. Кроме того, вы увидите некоторые библиотеки, в которых используется распознаватель, который взаимодействует с маршрутизатором, чтобы вы могли передавать больше, чем просто вызываемые функции. В принципе, Resolver гарантирует, что согласованный $handler
можно превратить в вызывающую функцию.
Кроме того, существует множество примеров и реализаций для этого, которые вы должны использовать вместо этого. Для моих личных проектов мне нравится FastRoute для удобства использования и производительности. Но почти все основные структуры имеют свои собственные реализации. Вы также должны проверить их.