前言
在开发项目时,我面临一个需求:区分移动端和桌面端访问路径。移动端访问应在路径前加上/m/
,而桌面端则不需要。例如:
- 移动端:
域名/m/路由地址
- 桌面端:
域名/路由地址
这种设计在路由规则上带来了一定的重复,因为相同的处理逻辑需要为两种不同的路径配置。例如,原始PHP路由配置如下:
# 不加上m写一次规则
Route::get('/register', 'Auth\RegisterController@showRegistrationForm');
# 加上m写一次规则
Route::get('/m/register', 'Auth\RegisterController@showRegistrationForm');
这导致代码重复,为了解决这个问题,我决定通过Nginx的地址重写功能来优化。
Nginx 配置
我在Nginx配置文件中添加了以下规则,以实现地址重写:
server {
listen 93;
server_name localhost;
root "F:/project/work/gameWeb/public/";
location /m/ {
rewrite ^/m/(.*)$ /$1 last;
}
location / {
index index.php index.html error/index.html;
try_files $uri $uri/ /index.php$is_args$args;
autoindex off;
}
location ~ \.php(.*)$ {
fastcgi_pass 127.0.0.1:9002;
fastcgi_index index.php;
fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param REQUEST_URI $request_uri;
}
}
尽管Nginx重写规则看似有效,但最终仍返回了Laravel的404页面,说明路由匹配失败。
结论与解决方案
问题出在以下这行配置:
fastcgi_param REQUEST_URI $request_uri;
在PHP中,$_SERVER[‘REQUEST_URI’] 获取的是重写前的URL,而不是重写后的。意味着即使URL被重写为不含 /m/ 的路径,REQUEST_URI 仍然包含 /m/。
为了验证这一点,我将上述行修改为:
fastcgi_param REQUEST_URI "/register";
这样,访问 域名/m/register 时,路由规则能成功匹配到:
Route::get('/register', 'Auth\RegisterController@showRegistrationForm');
这表明Laravel的路由匹配实际上是依赖于 REQUEST_URI 的值。因此,要解决这个问题,我觉得不是在于Nginx规则要改写REQUEST_URI,因为这会影响所有的项目。
最终解决方案
在 app\Providers\RouteServiceProvider.php 的代码文件中,修改boot方法
通过加入前缀路由的方式,来去除/m/带来的404问题
public function boot()
{
$this->configureRateLimiting();
$this->routes(function () {
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
// 不加m的路由
Route::namespace('App\User\Controller')
->group(base_path('routes/user.php'));
// 加了m的路由,将m视为前缀
Route::prefix('m')
->namespace('App\User\Controller')
->group(base_path('routes/user.php'));
});
}
补充知识点
框架 laravel/yii2 使用 $_SERVER[‘request_uri’] 中的路径做路由解析,不受rewrite影响
框架 thinkphp 使用 $_SERVER[‘path_info’] 中的路径做路由解析,受rewrite影响
两者最大的不同在于,nginx的rewrite重写后,获取到的路径是截然不同的
在 URL 重写(Rewrite)后的差异
- REQUEST_URI 变化:当使用 URL 重写(如在 Apache 的 .htaccess 或 Nginx 的 rewrite 规则)时,REQUEST_URI 通常会保持不变,反映原始请求的 URI。
- PATH_INFO 变化:PATH_INFO 可能会受到 URL 重写的影响。如果 URL 被重写到一个特定的脚本,PATH_INFO 可能会反映重写后的路径。
所以
thinkphp采用nignx的rewrite重写来实现去除/m/的影响理论上可行
但是laravel、YII则不能使用这种方案
这里博主没有去进行测试了