本文目录导读:

在 PHP 路由中匹配请求方式(HTTP Method)是 RESTful API 开发的基础,以下是几种常见的实现方式:
基础方法匹配
简单数组映射
class Router {
private $routes = [
'GET' => [],
'POST' => [],
'PUT' => [],
'DELETE' => []
];
public function add($method, $path, $handler) {
$this->routes[$method][$path] = $handler;
}
public function dispatch($method, $uri) {
$uri = parse_url($uri, PHP_URL_PATH);
if (!isset($this->routes[$method])) {
return "405 Method Not Allowed";
}
if (isset($this->routes[$method][$uri])) {
return call_user_func($this->routes[$method][$uri]);
}
// 尝试匹配动态路由
foreach ($this->routes[$method] as $route => $handler) {
$pattern = preg_replace('/\{([^}]+)\}/', '([^/]+)', $route);
if (preg_match("#^$pattern$#", $uri, $matches)) {
array_shift($matches);
return call_user_func_array($handler, $matches);
}
}
return "404 Not Found";
}
}
// 使用示例
$router = new Router();
$router->add('GET', '/users/{id}', function($id) {
return "获取用户 {$id}";
});
$router->add('POST', '/users', function() {
return "创建用户";
});
$method = $_SERVER['REQUEST_METHOD'];
$uri = $_SERVER['REQUEST_URI'];
echo $router->dispatch($method, $uri);
支持多个方法的组合路由
class Router {
private $routes = [];
public function add($methods, $path, $handler) {
// 支持单个或多个方法
$methods = is_array($methods) ? $methods : [$methods];
foreach ($methods as $method) {
$this->routes[$method][] = [
'path' => $path,
'handler' => $handler
];
}
}
public function get($path, $handler) {
return $this->add('GET', $path, $handler);
}
public function post($path, $handler) {
return $this->add('POST', $path, $handler);
}
public function put($path, $handler) {
return $this->add('PUT', $path, $handler);
}
public function delete($path, $handler) {
return $this->add('DELETE', $path, $handler);
}
public function any($path, $handler) {
return $this->add(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], $path, $handler);
}
public function dispatch($method, $uri) {
$uri = parse_url($uri, PHP_URL_PATH);
$uri = rtrim($uri, '/');
if (!isset($this->routes[$method])) {
return $this->methodNotAllowed();
}
foreach ($this->routes[$method] as $route) {
$pattern = $this->convertToPattern($route['path']);
if (preg_match($pattern, $uri, $matches)) {
array_shift($matches);
return call_user_func_array($route['handler'], $matches);
}
}
return $this->notFound();
}
private function convertToPattern($path) {
// 支持 {param} 和 {param:regex}
return '#^' . preg_replace(
'/\{(\w+)(?::([^}]+))?\}/',
'(?P<$1>$2)',
$path
) . '$#';
}
private function methodNotAllowed() {
http_response_code(405);
header('Allow: ' . implode(', ', array_keys($this->routes)));
return "405 Method Not Allowed";
}
private function notFound() {
http_response_code(404);
return "404 Not Found";
}
}
// 使用示例
$router = new Router();
$router->get('/users', function() {
return "获取用户列表";
});
$router->get('/users/{id}', function($id) {
return "获取用户 #{$id}";
});
$router->post('/users', function() {
$data = json_decode(file_get_contents('php://input'), true);
return "创建用户: " . json_encode($data);
});
$router->put('/users/{id}', function($id) {
return "更新用户 #{$id}";
});
$router->delete('/users/{id}', function($id) {
return "删除用户 #{$id}";
});
// 支持多个方法的组合
$router->any('/ping', function() {
return "Pong";
});
基于正则表达式的路由匹配
class AdvancedRouter {
private $routes = [];
public function route($method, $pattern, $handler) {
$this->routes[] = [
'method' => $method,
'pattern' => $pattern,
'handler' => $handler
];
}
public function dispatch($method, $uri) {
foreach ($this->routes as $route) {
// 检查方法是否匹配(支持通配符 *)
if ($route['method'] !== '*' && $route['method'] !== $method) {
continue;
}
if (preg_match($route['pattern'], $uri, $matches)) {
// 提取命名参数
$params = array_filter(
$matches,
'is_string',
ARRAY_FILTER_USE_KEY
);
return call_user_func_array(
$route['handler'],
array_merge([$method], $params)
);
}
}
return null;
}
}
// 使用示例
$router = new AdvancedRouter();
$router->route('GET', '#^/api/articles/(\d+)$#', function($method, $id) {
return "文章 #{$id}";
});
$router->route('*', '#^/api/status$#', function($method) {
return "方法: {$method}, 状态: OK";
});
方法覆盖(处理表单和兼容性)
class MethodOverrideRouter {
public function getActualMethod() {
$method = $_SERVER['REQUEST_METHOD'];
// 支持通过 _method 参数覆盖
if ($method === 'POST') {
if (isset($_POST['_method'])) {
$method = strtoupper($_POST['_method']);
} elseif (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) {
// 支持通过自定义头覆盖
$method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']);
}
}
return $method;
}
}
// 使用示例
$method = (new MethodOverrideRouter())->getActualMethod();
完整示例 - 小型 MVC 框架
class Router {
private $routes = [];
private $basePath = '';
public function __construct($basePath = '') {
$this->basePath = rtrim($basePath, '/');
}
public function add($method, $path, $handler, $name = null) {
$route = [
'method' => strtoupper($method),
'path' => $this->basePath . '/' . trim($path, '/'),
'handler' => $handler
];
if ($name) {
$route['name'] = $name;
}
$this->routes[] = $route;
return $this;
}
public function dispatch() {
$method = $_SERVER['REQUEST_METHOD'];
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
// 移除基础路径
if ($this->basePath && strpos($uri, $this->basePath) === 0) {
$uri = substr($uri, strlen($this->basePath));
}
$uri = '/' . trim($uri, '/');
foreach ($this->routes as $route) {
// 方法检查
if ($route['method'] !== $method) {
continue;
}
// 转换路由模式
$pattern = '#^' . preg_replace(
'/\{([^}]+)\}/',
'(?P<$1>[^/]+)',
$route['path']
) . '$#';
if (preg_match($pattern, $uri, $matches)) {
// 提取命名参数
$params = array_filter(
$matches,
'is_string',
ARRAY_FILTER_USE_KEY
);
if (is_callable($route['handler'])) {
return call_user_func_array($route['handler'], $params);
} else {
// 支持 "Controller@method" 格式
list($controller, $method) = explode('@', $route['handler']);
$controllerInstance = new $controller();
return call_user_func_array([$controllerInstance, $method], $params);
}
}
}
// 未找到路由
http_response_code(404);
return "404 Not Found";
}
}
// 控制器示例
class UserController {
public function show($id) {
return "显示用户 #{$id}";
}
public function store() {
return "创建用户";
}
}
// 使用示例
$router = new Router('/api');
$router->add('GET', '/users/{id}', function($id) {
return "获取用户 #{$id}";
});
$router->add('POST', '/users', function() {
$data = json_decode(file_get_contents('php://input'), true);
return "创建用户: " . json_encode($data);
});
$router->add('PUT', '/users/{id}', [new UserController(), 'show']);
echo $router->dispatch();
最佳实践建议
-
HTTP 方法语义化:
- GET:获取资源
- POST:创建资源
- PUT/PATCH:更新资源
- DELETE:删除资源
-
方法覆盖策略:
- 支持
X-HTTP-Method-Override头 - 支持
_method表单参数
- 支持
-
错误处理:
- 404:路由不存在
- 405:方法不允许(可以返回允许的方法列表)
-
性能优化:
- 使用前缀树(Trie)优化
- 缓存已编译的正则表达式
这些实现方式涵盖了从简单到复杂的各种场景,可以根据项目需求选择合适的方案。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播