Создание собственного роутера для PHP приложений
Основные методы работы с URL
Как организовать разбор URL в PHP для создания ЧПУ?
Наиболее эффективное решение для обработки URL в веб-приложении - создание класса-роутера. Он позволяет сопоставлять шаблоны маршрутов с обработчиками. Пример реализации:
class Router {
private $routes = [];
public function add($pattern, $callback) {
$this->routes[$pattern] = $callback;
}
public function match($uri) {
foreach ($this->routes as $pattern => $callback) {
if (preg_match($pattern, $uri, $matches)) {
array_shift($matches);
return call_user_func_array($callback, $matches);
}
}
return false;
}
}
// Использование:
$router = new Router();
$router->add('~^/$~', function() { echo 'Главная'; });
$router->add('~^/user/(\d+)$~', function($id) { echo "Пользователь $id"; });
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$router->match($uri);Php создание ссылки (создание ссылки в php)
Класс хранит массив маршрутов. Метод add принимает регулярное выражение (с разделителем ~) и замыкание. Метод match обходит маршруты, применяет preg_match и при совпадении вызывает обработчик, передавая захваченные группы.
Типичные ошибки и решения:
- Не учтён базовый путь приложения (если скрипт не в корне домена). Удаляйте префикс с помощью str_replace или константы.
- Параметры query string (после ?) попадают в URI. Используйте parse_url(..., PHP_URL_PATH) для извлечения пути.
- Регулярное выражение не соответствует UTF-8. Добавляйте модификатор u.
Вариант 1. Разбиение URI через explode
Вопрос: Как разбить URI на части без регулярных выражений?
$uri = $_SERVER['REQUEST_URI'];
$parts = explode('/', trim($uri, '/'));
$controller = $parts[0] ?? 'index';
$action = $parts[1] ?? 'default';
// Пример: /user/profile -> $controller='user', $action='profile'Php текущая url (текущая url в php)
Простой способ для небольших проектов. Не учитывает query string и требует дополнительной обработки.
- Query string (например, ?id=5) остаётся в последнем сегменте. Используйте strtok или parse_url для отделения.
- Пустой URI даёт массив с пустой строкой после trim. Проверяйте наличие элементов.
Вариант 2. Использование parse_url и parse_str
Вопрос: Как получить компоненты URL и параметры запроса в виде массива?
$url = 'http://example.com/page?name=value&id=5';
$parsed = parse_url($url);
$path = $parsed['path'] ?? '/';
parse_str($parsed['query'] ?? '', $query);
// $query['name'] = 'value'; $query['id'] = '5'Mobile php url (мобильный url в php)
Функция parse_url разбирает URL на компоненты (схема, хост, путь, query и т.д.). parse_str превращает строку запроса в ассоциативный массив.
- Если URL не содержит схему (например, /page?q=1), parse_url может интерпретировать его некорректно. Добавляйте префикс http:// при необходимости.
- Параметры с одинаковыми именами (например, a[]=1&a[]=2) parse_str обрабатывает как массив.
Вариант 3. Прямое применение регулярных выражений
Вопрос: Как задать шаблоны маршрутов с динамическими сегментами?
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
if (preg_match('~^/user/(\d+)/?$~', $uri, $matches)) {
$userId = $matches[1];
// ...
}
Подходит для небольшого числа маршрутов. Каждое условие обрабатывается отдельно.
- Сложность поддержки при росте количества маршрутов.
- Проблемы с производительностью при большом количестве проверок - лучше использовать единый роутер.
Расширенные примеры работы с URL
Роутер с поддержкой HTTP методов
Добавление проверки HTTP метода позволяет точно сопоставлять маршруты.
class MethodRouter {
private $routes = [];
public function add($method, $pattern, $handler) {
$this->routes[] = ['method' => strtoupper($method), 'pattern' => $pattern, 'handler' => $handler];
}
public function dispatch($uri, $method) {
$uri = parse_url($uri, PHP_URL_PATH);
foreach ($this->routes as $route) {
if ($route['method'] !== strtoupper($method)) continue;
if (preg_match($route['pattern'], $uri, $matches)) {
array_shift($matches);
return call_user_func_array($route['handler'], $matches);
}
}
http_response_code(404);
echo json_encode(['error' => 'Not Found']);
}
}
// Пример использования:
$router = new MethodRouter();
$router->add('GET', '~^/api/user/(\d+)$~', function($id) {
echo json_encode(['user_id' => $id]);
});
$router->add('POST', '~^/api/user$~', function() {
echo json_encode(['status' => 'created']);
});
$router->dispatch($_SERVER['REQUEST_URI'], $_SERVER['REQUEST_METHOD']);
При GET /api/user/42 ответ: {"user_id":42}
При POST /api/user ответ: {"status":"created"}
Обработка query string с помощью parse_str
Использование parse_str для преобразования строки запроса в массив.
$queryString = 'name=John&age=30&hobbies[]=reading&hobbies[]=coding';
parse_str($queryString, $result);
print_r($result);
Array
(
[name] => John
[age] => 30
[hobbies] => Array
(
[0] => reading
[1] => coding
)
)
Редирект на другой URL
Часто требуется перенаправить пользователя на другую страницу.
// Редирект на новый адрес
header('Location: /new-page');
exit;
// Редирект с параметрами
header('Location: /search?q=' . urlencode($query));
exit;
Важно: функция header должна быть вызвана до любого вывода. После редиректа всегда используйте exit.
Работа с фрагментом (якорь)
Фрагмент (#) не передаётся на сервер, но его можно получить на клиенте. Однако parse_url умеет его извлекать, если он есть в URL.
$url = 'https://example.com/page#section2';
$fragment = parse_url($url, PHP_URL_FRAGMENT);
echo $fragment; // section2
На сервере фрагмент обычно отсутствует, но при создании ссылок его можно использовать.
Валидация URL с помощью filter_var
Проверка корректности URL перед обработкой.
$url = 'https://example.com';
if (filter_var($url, FILTER_VALIDATE_URL)) {
echo 'URL корректен';
} else {
echo 'Некорректный URL';
}
URL корректен
Построение URL из компонентов
Для создания URL с параметрами удобно использовать http_build_query.
$base = '/search';
$params = ['q' => 'php', 'page' => 2];
$url = $base . '?' . http_build_query($params);
echo $url;
/search?q=php&page=2