本文目录导读:

在 PHP 中“请求路由”通常有两种理解:前端路由(通过 URL 重写实现)和后端路由(框架或原生实现),下面我分别讲解。
基础环境配置(Apache/Nginx)
Apache (.htaccess)
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
Nginx
location / {
try_files $uri $uri/ /index.php?url=$uri;
}
原生 PHP 实现路由
方式1:基于 URL 参数(简单版)
<?php
// index.php
$path = $_GET['url'] ?? '/';
// 路由表
$routes = [
'/' => 'home',
'/users' => 'user_list',
'/users/create' => 'user_create',
];
if (isset($routes[$path])) {
// 处理逻辑
echo "执行: " . $routes[$path];
} else {
http_response_code(404);
echo "404 Not Found";
}
方式2:正则匹配(更灵活)
<?php
// index.php
$path = $_GET['url'] ?? '/';
// 去掉尾部的斜杠
$path = rtrim($path, '/');
$routes = [
'/^\/users$/' => ['controller' => 'UserController', 'method' => 'index'],
'/^\/users\/(\d+)$/' => ['controller' => 'UserController', 'method' => 'show'],
'/^\/users\/create$/' => ['controller' => 'UserController', 'method' => 'create'],
];
foreach ($routes as $pattern => $handler) {
if (preg_match($pattern, $path, $matches)) {
$controller = new $handler['controller']();
array_shift($matches); // 移除第一个匹配项(整个匹配串)
// 调用控制器方法,并传递参数
call_user_func_array([$controller, $handler['method']], $matches);
exit;
}
}
http_response_code(404);
echo "页面不存在";
面向对象实现路由(推荐)
创建 Router 类
<?php
// Router.php
class Router {
private $routes = [];
// 注册 GET 路由
public function get($path, $callback) {
$this->routes['GET'][$path] = $callback;
}
// 注册 POST 路由
public function post($path, $callback) {
$this->routes['POST'][$path] = $callback;
}
// 解析当前请求
public function resolve() {
$method = $_SERVER['REQUEST_METHOD'];
$path = $_GET['url'] ?? '/';
// 去除路径中的查询字符串
$path = explode('?', $path)[0];
foreach ($this->routes[$method] ?? [] as $route => $handler) {
// 支持 {id} 这样的参数占位符
$pattern = preg_replace('/\{([a-zA-Z0-9_]+)\}/', '([^/]+)', $route);
$pattern = "@^" . $pattern . "$@";
if (preg_match($pattern, $path, $matches)) {
array_shift($matches);
return call_user_func_array($handler, $matches);
}
}
// 没有匹配的路由
http_response_code(404);
echo "404 Not Found";
}
}
使用 Router
<?php
// index.php
require_once 'Router.php';
$router = new Router();
// 定义路由
$router->get('/', function() {
echo '首页';
});
$router->get('/users', function() {
echo '用户列表';
});
$router->get('/users/{id}', function($id) {
echo "查看用户 ID: $id";
});
$router->post('/users', function() {
echo '创建新用户';
});
// 启动路由
$router->resolve();
PHP 框架实现(Laravel 示例)
Laravel 路由
// routes/web.php
use App\Http\Controllers\UserController;
Route::get('/', function () {
return view('welcome');
});
Route::get('/users', [UserController::class, 'index']);
Route::get('/users/{id}', [UserController::class, 'show']);
Route::post('/users', [UserController::class, 'store']);
Route::put('/users/{id}', [UserController::class, 'update']);
Route::delete('/users/{id}', [UserController::class, 'destroy']);
// 带中间件的路由
Route::middleware(['auth'])->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index']);
Route::resource('posts', PostController::class);
});
Laravel 路由参数和条件
// 必选参数
Route::get('/user/{id}', function ($id) {
return "User ID: $id";
});
// 可选参数
Route::get('/search/{query?}', function ($query = null) {
return $query ? "搜索: $query" : "默认搜索";
});
// 正则约束
Route::get('/user/{id}', function ($id) {
return "User $id";
})->where('id', '[0-9]+');
// 命名路由
Route::get('/profile', function () {
return '个人中心';
})->name('profile');
// 使用命名路由生成 URL
echo route('profile');
完整示例:一个简单的 REST 风格路由系统
<?php
// index.php - 完整路由系统
class SimpleRouter {
private static $routes = [];
public static function add($method, $path, $callback) {
self::$routes[] = [
'method' => strtoupper($method),
'path' => $path,
'callback' => $callback
];
}
public static function get($path, $callback) {
self::add('GET', $path, $callback);
}
public static function post($path, $callback) {
self::add('POST', $path, $callback);
}
public static function dispatch() {
$requestMethod = $_SERVER['REQUEST_METHOD'];
$requestPath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
foreach (self::$routes as $route) {
if ($route['method'] === $requestMethod) {
$pattern = preg_replace('/\{(\w+)\}/', '([^/]+)', $route['path']);
$pattern = str_replace('/', '\/', $pattern);
if (preg_match('/^' . $pattern . '$/', $requestPath, $matches)) {
array_shift($matches);
return call_user_func_array($route['callback'], $matches);
}
}
}
http_response_code(404);
echo json_encode(['error' => 'Not Found']);
}
}
// 定义路由
SimpleRouter::get('/api/users', function() {
echo json_encode(['status' => 'success', 'data' => ['user1', 'user2']]);
});
SimpleRouter::get('/api/user/{id}', function($id) {
echo json_encode(['status' => 'success', 'user_id' => $id]);
});
SimpleRouter::post('/api/login', function() {
$data = json_decode(file_get_contents('php://input'), true);
echo json_encode(['status' => 'login success', 'data' => $data]);
});
// 启动路由
SimpleRouter::dispatch();
最佳实践建议
-
使用分层的目录结构
/ ├── public/ │ └── index.php # 入口文件 ├── app/ │ ├── Controllers/ # 控制器 │ ├── Models/ # 模型 │ ├── Views/ # 视图 │ └── Middleware/ # 中间件 ├── routes/ │ └── web.php # 路由定义 └── config/ └── config.php # 配置文件 -
缓存路由表提升性能(生产环境)
-
验证和过滤路由参数
-
使用中间件处理认证、日志、CORS等
查询现有框架
- Laravel - 重型框架,功能最全
- Symfony - 企业级框架
- ThinkPHP - 国内流行的中文框架
- FastRoute - 高性能路由库
- Phalcon - C 扩展实现,性能极高
如果项目较小,直接使用上述原生实现即可;大型项目建议使用成熟框架来管理路由。