本文目录导读:

在PHP中编写路由重写规则主要有两种方式:服务器配置(Apache/Nginx)和 PHP路由器,下面分别详细说明:
服务器配置层(重写URL)
Apache服务器(.htaccess)
# 启用重写引擎
RewriteEngine On
# 如果不是真实存在的文件或目录,则重写到index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
# 或者更复杂的规则
RewriteRule ^article/([0-9]+)$ article.php?id=$1 [L]
RewriteRule ^page/([a-z]+)$ page.php?name=$1 [L]
Nginx服务器
server {
listen 80;
server_name yourdomain.com;
root /var/www/html;
index index.php;
# 将所有请求重写到index.php
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# 更具体的规则
location ~ ^/article/(\d+)$ {
rewrite ^/article/(\d+)$ /article.php?id=$1 last;
}
location ~ ^/page/([a-z]+)$ {
rewrite ^/page/([a-z]+)$ /page.php?name=$1 last;
}
# PHP处理
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
PHP后端路由处理
简单的前端控制器
<?php
// index.php - 前端控制器
// 获取请求的URL
$request_uri = $_SERVER['REQUEST_URI'];
$base_path = dirname($_SERVER['SCRIPT_NAME']);
$path = substr($request_uri, strlen($base_path));
// 移除查询字符串
if (strpos($path, '?') !== false) {
$path = substr($path, 0, strpos($path, '?'));
}
$path = trim($path, '/');
$segments = $path ? explode('/', $path) : [];
// 默认路由
$controller = 'HomeController';
$action = 'index';
// 解析路由
if (isset($segments[0]) && $segments[0] !== '') {
$controller = ucfirst($segments[0]) . 'Controller';
}
if (isset($segments[1])) {
$action = $segments[1];
}
// 调用对应的控制器和方法
$controller_file = __DIR__ . '/controllers/' . $controller . '.php';
if (file_exists($controller_file)) {
require_once $controller_file;
$controller_instance = new $controller();
if (method_exists($controller_instance, $action)) {
$params = array_slice($segments, 2);
call_user_func_array([$controller_instance, $action], $params);
} else {
die('404 Not Found');
}
} else {
die('404 Not Found');
}
?>
高级路由类
<?php
// Router.php
class Router {
private $routes = [];
private $base_path = '';
public function __construct($base_path = '') {
$this->base_path = $base_path;
$this->parseRequest();
}
// 添加GET路由
public function get($route, $callback) {
$this->addRoute('GET', $route, $callback);
}
// 添加POST路由
public function post($route, $callback) {
$this->addRoute('POST', $route, $callback);
}
private function addRoute($method, $route, $callback) {
$this->routes[$method][$route] = $callback;
}
private function parseRequest() {
$uri = $_SERVER['REQUEST_URI'];
$base_path = $this->base_path;
if (strpos($uri, $base_path) === 0) {
$uri = substr($uri, strlen($base_path));
}
$uri = trim($uri, '/');
$this->path = $uri ?: '/';
$this->method = $_SERVER['REQUEST_METHOD'];
}
// 匹配路由
public function match() {
$path = rtrim($this->path, '/') ?: '/';
if (isset($this->routes[$this->method][$path])) {
$this->call($this->routes[$this->method][$path], []);
return true;
}
// 正则匹配带参数的路由
foreach ($this->routes[$this->method] ?? [] as $route => $callback) {
$pattern = preg_replace('/\{(\w+)\}/', '(?P<\1>[^/]+)', $route);
$pattern = '@^' . $pattern . '$@';
if (preg_match($pattern, $path, $matches)) {
$params = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);
$this->call($callback, array_values($params));
return true;
}
}
return false;
}
private function call($callback, $params) {
if (is_callable($callback)) {
call_user_func_array($callback, $params);
} elseif (is_string($callback) && strpos($callback, '@') !== false) {
list($controller, $method) = explode('@', $callback);
require_once "controllers/{$controller}.php";
$obj = new $controller();
$obj->$method(...$params);
}
}
}
// 使用示例
// index.php
$router = new Router('/myapp');
$router->get('/', function() {
echo 'Home Page';
});
$router->get('/user/{id}', 'UserController@show');
$router->post('/user/create', 'UserController@create');
if (!$router->match()) {
header('HTTP/1.1 404 Not Found');
echo '404 Not Found';
}
?>
RESTful API路由示例
<?php
// api.php
class ApiRouter {
private $routes = [];
public function get($route, $callback) {
$this->add('GET', $route, $callback);
}
public function post($route, $callback) {
$this->add('POST', $route, $callback);
}
private function add($method, $route, $callback) {
$this->routes[] = [
'method' => $method,
'route' => $route,
'callback' => $callback
];
}
public function handle() {
$method = $_SERVER['REQUEST_METHOD'];
$uri = $_SERVER['REQUEST_URI'];
$uri = rtrim($uri, '/');
$uri = urldecode($uri);
foreach ($this->routes as $route) {
if ($route['method'] === $method) {
$pattern = $this->patternToRegex($route['route']);
if (preg_match($pattern, $uri, $matches)) {
$params = [];
foreach ($matches as $key => $value) {
if (!is_int($key)) {
$params[$key] = $value;
}
}
call_user_func_array($route['callback'], array_values($params));
return true;
}
}
}
return false;
}
private function patternToRegex($pattern) {
$pattern = preg_replace('/\//', '\/', $pattern);
$pattern = preg_replace('/\{(\w+)\}/', '(?P<$1>[^/]+)', $pattern);
return '/^' . $pattern . '$/';
}
}
// 使用
$api = new ApiRouter();
$api->get('/api/users', function() {
// 返回所有用户
echo json_encode(['users' => []]);
});
$api->get('/api/users/{id}', function($id) {
// 返回指定用户
echo json_encode(['user' => $id]);
});
$api->post('/api/users', function() {
$data = json_decode(file_get_contents('php://input'), true);
// 创建新用户
echo json_encode(['status' => 'created']);
});
if (!$api->handle()) {
header('HTTP/1.1 404 Not Found');
echo json_encode(['error' => 'Not Found']);
}
?>
URL重写的常见场景
伪静态页面
/article/123 → article.php?id=123
/category/tech → category.php?name=tech
/tag/php → tag.php?name=php
用户友好URL
/profile/john → user.php?username=john
/orders/2023/01 → orders.php?year=2023&month=01
分页URL
/products/page/2 → products.php?page=2
/news/page/3 → news.php?page=3
最佳实践建议
- 使用Composer配合成熟路由库:如 FastRoute、Slim Framework、Laravel 的 Router
- 保持路由规则简单:避免过于复杂的正则表达式
- 缓存编译后的路由:提高性能
- 使用绝对路径:避免相对路径带来的混乱
- 支持RESTful风格:让你的API更规范
选择哪种方式取决于你的项目规模和需求,对于简单项目,直接用服务器配置或简单PHP代码即可;对于大型项目,建议使用成熟框架或Composer库。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播