O ramură pentru fiecare rută
Rutarea decide care cod răspunde la care cerere. PHP nu are un tabel de rute încorporat — scriptul de rutare citește singur cererea: $_SERVER["REQUEST_URI"] conține calea, iar despărțirea ei după / dă segmentele.
Un segment care este date — 7 din /users/7 — este un parametru de cale: în loc să îl potrivească literal, routerul îl captează și îl dă handlerului. Framework-urile adaugă facilități deasupra, dar acesta este mecanismul de dedesubt.
Rute și valori din cale
Două rute: lista la /users și un singur utilizator la /users/{id}. Al doilea segment al căii este parametrul de cale — bucata din URL care este date.
O rută cu un parametru de cale
Același script de rutare trimite /users către o ramură și /users/7 către alta, iar al doilea segment al căii predă valoarea 7 ca date.
Ieșire: script PHP
<?php
// Scriptul de rutare: desparte calea și alege o ramură.
$router = <<<'PHP'
<?php
$path = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
$segments = explode("/", trim($path, "/"));
if ($path === "/users") {
echo "toți utilizatorii: Ana, Ben, Cleo\n";
} elseif (count($segments) === 2 && $segments[0] === "users") {
echo "un utilizator, id = {$segments[1]}\n";
} else {
http_response_code(404);
echo "nu a fost găsit\n";
}
PHP;
$routerFile = sys_get_temp_dir() . "/pc-path-values.php";
file_put_contents($routerFile, $router);
// Un port liber, apoi serverul web încorporat al PHP ca proces-copil.
$probe = stream_socket_server("tcp://127.0.0.1:0");
$port = (int) explode(":", stream_socket_get_name($probe, false))[1];
fclose($probe);
$server = proc_open(["php", "-S", "127.0.0.1:$port", $routerFile],
[1 => ["file", "/dev/null", "w"], 2 => ["file", "/dev/null", "w"]], $pipes);
do {
usleep(20000);
$up = @fsockopen("127.0.0.1", $port);
} while ($up === false);
fclose($up);
$context = stream_context_create(["http" => ["ignore_errors" => true]]);
foreach (["/users", "/users/7"] as $path) {
$body = file_get_contents("http://127.0.0.1:$port$path", false, $context);
echo "GET $path -> $body";
}
proc_terminate($server);
proc_close($server);
unlink($routerFile);
Parametri de interogare
Partea de după ? conține parametrii de interogare — opțiuni pentru cerere, cum ar fi un text de căutare sau o limită: /search?q=php&limit=2. PHP îi analizează în locul tău în tabloul $_GET, mereu ca șiruri de caractere, iar ?? furnizează o valoare implicită pentru cei care lipsesc.
Regula practică: calea spune care resursă, interogarea spune cum — filtrare, sortare, paginare.
Citirea șirului de interogare
Handlerul citește q și limit din $_GET. A doua cerere omite limit, așa că handlerul revine la o valoare implicită — parametrii lipsă sunt un lucru normal, ține cont de ei.
Ieșire: script PHP
<?php
// Parametrii de interogare ajung deja analizați în $_GET, mereu ca șiruri de caractere.
$router = <<<'PHP'
<?php
$q = $_GET["q"] ?? "";
$limit = $_GET["limit"] ?? "10";
echo "se caută $q cu limita $limit\n";
PHP;
$routerFile = sys_get_temp_dir() . "/pc-query-params.php";
file_put_contents($routerFile, $router);
// Un port liber, apoi serverul web încorporat al PHP ca proces-copil.
$probe = stream_socket_server("tcp://127.0.0.1:0");
$port = (int) explode(":", stream_socket_get_name($probe, false))[1];
fclose($probe);
$server = proc_open(["php", "-S", "127.0.0.1:$port", $routerFile],
[1 => ["file", "/dev/null", "w"], 2 => ["file", "/dev/null", "w"]], $pipes);
do {
usleep(20000);
$up = @fsockopen("127.0.0.1", $port);
} while ($up === false);
fclose($up);
$context = stream_context_create(["http" => ["ignore_errors" => true]]);
foreach (["/search?q=php&limit=2", "/search?q=json"] as $path) {
$body = file_get_contents("http://127.0.0.1:$port$path", false, $context);
echo "GET $path -> $body";
}
proc_terminate($server);
proc_close($server);
unlink($routerFile);