为了减少部署时ssl证书申请,降低配置成本想把所有laravel的前端工程配置在一个域名下,结果就卡在二级目录设置这块怎么都出不来结果,也没发现有哪篇文章能详细写一下这种情况下如何配置(可能对于大神来说这种问题是太简单了吧)。现在就把过程中遇到的问题写下来
本地目录配置:
/data/www/www.aaa.com |___ index.html |___ /bbb-laravel-web |___ resources |___ public | |___ index.php | |___ css | |___ ccc.page.css |____ ...(其他目录略)
最终想达到的效果是:
浏览器输入www.aaa.com,访问的是/data/www/www.aaa.com/index.html 浏览器输入www.aaa.com/bbb/,访问的是laravel的主页 也就是/data/www/www.aaa.com/bbb-laravel-web/public/index.php
一开始就按着访问后台接口的方式配置的
server { listen 80; listen 443; # ssl 部分省略; server_name www.aaa.cn; root /data/www/www.aaa.cn; access_log /data/log/nginx/www.aaa.cn.access.log main; error_log /data/log/nginx/www.aaa.cn.error.log debug; location /{ index index.php index.html; } location ^~ /bbb/ { try_files $uri /bbb-laravel-web/public/index.php; index index.html index.htm; index index.html index.php; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi.conf; set $script $uri; set $path_info "/"; if ( $uri ~ "^(.+\.php)(.+)$" ) { set $script $1; set $path_info $2; } fastcgi_param APP_ENV debug;#这里是使得laravel读取.env.debug下的配置,laravel5.5及以上可以那么搞 fastcgi_param PATH_INFO $path_info; fastcgi_param SCRIPT_FILENAME $document_root/$script; fastcgi_param SCRIPT_NAME $script; } }
结果出现了
让我们看看都这段发生了什么:
1.首先去查看/data/log/nginx/www.aaa.cn.error.log
2018/08/20 15:25:45 [notice] 2685#2685: *6 "^(.+\.php)(.+)$" does not match "/bbb-laravel-web/public/index.php", client: 123.45.678.90, server: www.aaa.cn, request: "GET /bbb/ HTTP/1.1", host: "www.aaa.cn"
为什么会出现不匹配的情况呢?
1.匹配流程
首先,nginx拿到www.aaa.com/bbb/匹配的是下面这段配置
location ^~ /bbb/ { try_files $uri /bbb-laravel-web/public/index.php; index index.html index.htm; index index.html index.php; }
我们从开头的本地磁盘root目录(也就是/data/www/www.aaa.cn)下面是没有bbb文件夹,所以$uri是匹配不上的,这个时候就匹配到了“/bbb-laravel-web/public/index.php”。由于它是try_files的最后一项,所以就发生了一个重定向,重定向匹配到了下面这段
location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi.conf; set $script $uri; set $path_info "/"; if ( $uri ~ "^(.+\.php)(.+)$" ) { set $script $1; set $path_info $2; } fastcgi_param APP_ENV debug;#这里是使得laravel读取.env.debug下的配置,laravel5.5及以上可以那么搞 fastcgi_param PATH_INFO $path_info; fastcgi_param SCRIPT_FILENAME $document_root/$script; fastcgi_param SCRIPT_NAME $script; } }
这段发生了什么呢?我们先来列举下里面的变量
整个url:www.aaa.com/bbb-laravel-web/public/index.php set $script $uri; # $script=$uri=/bbb-laravel-web/public/index.php set $path_info "/"; # $path_info="/" if ( $uri ~ "^(.+\.php)(.+)$" ) { set $script $1; # $script=(.+\.php) set $path_info $2; # $path_info=(.+) } fastcgi_param PATH_INFO $path_info; fastcgi_param SCRIPT_FILENAME $document_root/$script; fastcgi_param SCRIPT_NAME $script;
这段是解析php的,重写了url,访问index.php下路由为变量path_info的页面:
如果匹配不上"^(.+.php)(.+)$",那么就访问路由为/的页面
如果匹配上了,就访问路由(.+)的页面。这个配置逻辑是没有问题的。
由于(.+)表示的是匹配任意字符1~n次,那么/bbb-laravel-web/public/index.php是匹配不上,这时应该访问路由为"/"的页面,那又为什么访问不了呢?
我一开始是怀疑是nginx配置的问题,但是这个404页面是laravel的,说明是可以访问到laravel的,只是laravel内部没有这个路由,但是实际上我是写了"/"路由的。那么laravel内部接收到的是什么路由呢?
本来想着去看一把Laravel内部路由执行的原理,找个地方打log。但是太耗时间了,这个时候用了点小聪明,既然不是“/”的话,那么还有可能的路由便是"/bbb/",于是在app/Provider/RouteServiceProvider.php里面给web路由加了个前缀
protected function mapWebRoutes() { Route::prefix('bbb') //这个就是加了的前缀 ->middleware('web') ->namespace($this->namespace) ->group(base_path('routes/web.php')); }
然后再测试,居然能访问到“/”路由了,但是页面样式却没了。
问题终于解决了第一步,接下来我们来解决第二步。
首先是看看样式文件为什么没访问到。
这个时候可以在浏览器里右键查看源代码,然后点击样式文件的链接(链接如下)
,结果404了。
<link href="./css/ccc.page.css" rel="stylesheet" type="text/css">
接着就上服务器上看看nginx的error log,log的位置就在上面的配置中
error_log /data/log/nginx/www.aaa.cn.error.log debug;
唔,就是上面这行,中间的是路径,最后的debug表示了log的级别
然后看到了这一行
2018/08/21 08:58:50 [error] 11646#11646: *360 open() "/data/www/www.aaa.cn/bbb/css/ccc.page.css" failed (2: No such file or directory), client: 123.45.678.90, server: www.aaa.cn, request: "GET /bbb/css/ccc.page.css HTTP/1.1", host: "www.aaa.cn", referrer: "https://www.aaa.cn/bbb/"
我们看到开始的目录就知道,/data/www/www.aaa.cn是没有bbb文件夹的,那访问bbb/css/ccc.page.css一定是404。要解决这个问题,那就得重写请求了。
location ^~ /bbb { location ~* ^(.+)\.(gif|jpg|jpeg|png|css|js|ico)$ { # rewrite语法:rewrite 正则表达式 目标文件 [flag] # ^表示正则表达式起始,$表示正则表达式结束 # $1,$2,$3表示正则表达式中不同的匹配部分 # $2和$3中间的“\.”表示.号。因为.在正则表达式里是匹配 # 在这里 $1=([a-zA-Z0-9]{3,}),$2=(.+),$3=(gif|jpg|jpeg|png|css|js|ico) rewrite '^/bbb/([a-zA-Z0-9]{3,})/(.+)\.(gif|jpg|jpeg|png|css|js|ico)$' /bbb-web-laravel/public/$1/$2.$3 last; } try_files $uri /bbb-laravel-web/public/index.php; #root html; index index.html index.htm; index index.html index.php; }
这下好了,不过我寻思着,这个配置能不能再优化下。比如把所有请求都写在public下面,最后的配置如下
location ^~ /meetdate { alias /data/www/www.aaa.cn/bbb-laravel-web/public; rewrite '^/meetdate(.*)' /bbb-laravel-web/public$1 last; }
然后发现SCSS里面的配置url("/image/a.png")路径访问不到,查看源代码发现的路径变成了www.aaa.com/image/a.png,那当然访问不了。然后去看了laravel-sass的文档
这段话说了两个意思:
1.对于相对路径而言,laravel会在resource(请看最前面的本地路径)下寻找相关的图片文件拷贝到public/images下,然后url重写成了/images/a.png?xxxxxxx
2.对于绝对路径,laravel不会进行url重写
那么像我这种希望不重写,以便最终编译成"../images/a.png"的怎么办呢?
文档也给出了解决办法,就是编译sass的语句后面加上options,代码如下
mix.sass('resources/assets/app/app.scss', 'public/css') .options({ processCssUrls: false });
然后就OK了!
以上就是“记一次laravel把工程文件配置在nginx二级目录并怎么读取的问题”的详细内容,想要获取更多laravel教程欢迎关注编程学习网
扫码二维码 获取免费视频学习资料
- 本文固定链接: http://phpxs.com/post/8242/
- 转载请注明:转载必须在正文中标注并保留原文链接
- 扫码: 扫上方二维码获取免费视频资料