フレームワークとライブラリが Router と Dispatcher の役割を解釈する方法は異なります。以下で詳しく説明するのは、これら 2 つのサービスの責任をどのように解釈するかです。これがそれを解釈する唯一の方法であるとか、他の解釈が間違っていると言っているわけではありません。
コンセプト
ルーティング
これは、ガソリンスタンドやコンビニで道を尋ねるようなものです。あなたは町を通り抜けており、最寄りのホテルへの行き方を把握する必要があります。中に入って係員に尋ねると、彼らは正しい方向を示してくれます。少なくとも、方向が正しいことを願っています。ルーティングはまさにこれです。リソースに対するリクエストが届くと、ルーターはリクエストが正しいリソースに到達するために必要な指示を提供します。
ほとんどの主要なフレームワークでは、特定のリクエスト URL を、リクエストを完了するために呼び出されるオブジェクトとメソッドにルーティングします。多くの場合、Router が URL から動的引数を解析しているのも見られます。たとえば、/users/1234
where 1234
is the user ID を介してユーザーにアクセスした場合、Router は ID 部分を解析し、これをリソースへの指示の一部として提供します。
派遣
ディスパッチでは、ルーティング ステップからの情報を使用して、実際にリソースを生成します。ルーティングステップが指示を求めている場合、発送はその指示に従う実際のプロセスです。Dispatching は、何を作成するか、およびリソースを生成するために必要な手順を正確に認識しますが、Router から指示を取得した後でのみです。
実装
これらの実装例は、意図的に非常に単純で単純です。劇的な改善なしに、あらゆる種類の本番環境でこれを使用したくないでしょう。
この例では、オブジェクトとメソッドにルーティングする代わりに、呼び出し可能な関数にルーティングします。これは、オブジェクトにルーティングする必要がないことも示しています。ディスパッチャーが正しいリソースを適切に取得できる限り、必要なデータにルーティングできます。
まず、ルーティングする対象が必要です。照合できる単純な 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;
}
}
何かと照合できるようになったので、単純な Router の実装を見てみましょう。
<?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を調べると、この実装の実際の例を見ることができます。
まとめ
この実装例は、ルーティングとディスパッチの概念を伝えることになっています。実際には、これらのアクションを実行するには、私の例よりも多くのことがあります。多くの場合、Router は正規表現を使用して Request と照合し、照合時に他の Request 属性を調べることがあります。さらに、ルーターと対話するリゾルバーを利用するいくつかのライブラリが表示されるため、呼び出し可能な関数以上のものを渡すことができます。基本的に、Resolver は、$handler
一致したものを呼び出し可能な関数に変換できるようにします。
また、代わりに使用することを検討すべき多くの例と実装があります。私の個人的なプロジェクトでは、FastRouteの使いやすさとパフォーマンスが気に入っています。ただし、ほとんどすべての主要なフレームワークには独自の実装があります。そちらも要チェックです。