PHP伪静态与URL路由详解
PHP伪静态与URL路由详解
URL重写让动态URL变成静态形式,对SEO和用户体验有好处。今天说说PHP中URL路由和伪静态的实现。
URL重写通过Web服务器配置实现。
```apache
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
```
PHP端的路由解析。
```php
class Router
{
private array $routes = [];
public function get(string $uri, callable $handler): void
{
$this->addRoute('GET', $uri, $handler);
}
public function post(string $uri, callable $handler): void
{
$this->addRoute('POST', $uri, $handler);
}
private function addRoute(string $method, string $uri, callable $handler): void
{
$uri = preg_replace('/\{(\w+)\}/', '(?P<$1>[^/]+)', $uri);
$this->routes[$method][] = ['pattern' => '#^' . $uri . '$#', 'handler' => $handler];
}
public function dispatch(string $method, string $uri): void
{
$uri = parse_url($uri, PHP_URL_PATH);
foreach ($this->routes[$method] ?? [] as $route) {
if (preg_match($route['pattern'], $uri, $matches)) {
$params = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);
echo ($route['handler'])($params);
return;
}
}
http_response_code(404);
echo "404 Not Found";
}
}
$router = new Router();
$router->get('/articles/{id}', fn($p) => "文章 #{$p['id']}");
$router->get('/articles/{id}/edit', fn($p) => "编辑文章 #{$p['id']}");
$router->get('/users/{id}/posts/{postId}', fn($p) => "用户{$p['id']}的文章{$p['postId']}");
$router->dispatch('GET', '/articles/42');
echo "\n";
$router->dispatch('GET', '/articles/42/edit');
echo "\n";
$router->dispatch('GET', '/users/1/posts/10');
echo "\n";
?>
路由中的中间件支持。
```php
class RouteWithMiddleware
{
private array $routes = [];
private array $globalMiddlewares = [];
public function addMiddleware(callable $middleware): void
{
$this->globalMiddlewares[] = $middleware;
}
public function get(string $uri, callable $handler, array $middlewares = []): void
{
$this->routes['GET'][] = compact('uri', 'handler', 'middlewares');
}
public function dispatch(string $method, string $uri): void
{
$uri = parse_url($uri, PHP_URL_PATH);
foreach ($this->routes[$method] ?? [] as $route) {
$pattern = preg_replace('/\{(\w+)\}/', '(\w+)', $route['uri']);
$pattern = '#^' . $pattern . '$#';
if (preg_match($pattern, $uri, $matches)) {
array_shift($matches);
$allMiddlewares = array_merge($this->globalMiddlewares, $route['middlewares']);
$handler = $route['handler'];
foreach (array_reverse($allMiddlewares) as $mw) {
$next = $handler;
$handler = fn($params) => $mw($params, $next);
}
echo $handler($matches);
return;
}
}
http_response_code(404);
}
}
?>
路由参数验证。
```php
class RouteValidator
{
private array $patterns = [
'id' => '\d+',
'slug' => '[a-z0-9-]+',
'uuid' => '[0-9a-f-]+',
];
public function pattern(string $name, string $pattern): void
{
$this->patterns[$name] = $pattern;
}
}
?>
URL路由框架的核心就是URL匹配和参数提取。理解了路由的原理,不管是配置框架路由还是排查路由问题,心里都有底了。伪静态URL让地址更美观,对搜索引擎也更友好。
