我已经找到了一种可能的方法,可以在一个NGINX服务器上动态地处理多个Laravel项目(所以在一个foldder中,每个laravel项目可能有多个文件夹。每个laravel项目的入口点是index.php
所在的/public
文件夹)。这背后的主要思想是通过添加一个新的文件夹来轻松安装新的laravel项目,并能够通过我的子域和路径访问它。像www.webs.example.com/my-new-project
全部归功于Henno
这是我的域名的NGINX conf
# Capture $project from /$projectname/controller/action
map $request_uri $project {
~^/(?<captured_project>[a-zA-Z0-9_-]+)/? $captured_project;
default / ;
}
server {
listen 443; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/webs.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/webs.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
server_name webs.example.com www.webs.example.com;
# Use $project/public as root
root /var/www/laravel/$project/public;
# Use index.php as directory index
index index.php;
# Include the basic h5bp config set (see https://github.com/h5bp/server-configs-nginx)
# include h5bp/basic.conf;
# Process /projectname/the/rest/of/the/url
location ~ ^/([^/]+)/(.*) {
# Save the rest of the URL after project name as $request_url
set $request_url /$2;
# If the saved url refers to a file in public folder (a static file), serve it,
# else redirect to index.php, passing along any ?var=val URL parameters
try_files $uri $request_url /index.php?$is_args$args;
}
# Process any URL containing .php (we arrive here through previous location block)
# If you don't need to serve any other PHP files besides index.php, use location /index.php here
# instead, to prevent possible execution of user uploaded PHP code
location ~ [^/]\.php(/|$) {
# Define $fastcgi_script_name and $fastcgi_path_info
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
# Immediately return 404 when script file does not exist
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
# Mitigate https://httpoxy.org/ vulnerabilities
fastcgi_param HTTP_PROXY "";
# Define PHP backend location (find yours by grepping "listen ="
# from your PHP config folder, e.g. grep -r "listen =" /etc/php/)
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
# Set SCRIPT_FILENAME to execute
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# Include the default fastcgi parameters
include fastcgi_params;
# Overwrite REQUEST_URI (default is $request_uri) with $request_url we saved earlier
fastcgi_param REQUEST_URI $request_url;
}
}
字符串
此配置适用于Web入口点**
如果我访问webs.example.com/<project_name>
(例如webs.example.com/myProject)我得到一个呈现的索引页面。因此,请求被正确处理以运行/var/www/laravel/<project_name>/public/index.php
文件。
然而,页面却“残破不堪”
它的破坏,因为所有的资源(如css和js文件,图像,...)都在文件夹/public/resources
和/public/images
中,并在代码中访问,如
<link rel="stylesheet" href="{{ asset('/resources/fontawesome/css/all.css') }}">
<img src="{{ url('/') }}{{$banner->image}}" alt="" class="img-fluid">
型
这将分别导致url webs.example.com/resources/fontawesome/css/all.css
和webs.example.com/images/banners/1.jpg
($banner->图像包含/images/banners/1.jpg)
这是没有找到的明显原因-有一个失踪的部分在网址,网址不包含项目名称,因为它应该。
所以正确的URL是(<project_name>是URL的动态部分,如myProject)
webs.example.com/<project_name>/resources/fontawesome/css/all.css
webs.example.com/<project_name>/images/banners/1.jpg
型
在我看来,这可能是由于NGINX配置不好造成的。因为当我尝试将Web根路径硬编码到其/public文件夹(/var/www/laravel/myProject/public)时,一切正常。因此,我正在寻求一个选项来实现这一点,默认情况下,在一些文件夹中的所有项目。在Apache上,这工作得很好
在Apache中(我正在从Apache迁移到NGINX,并且一切正常),有一种简单的方法可以解决这个问题,通过添加.htaccess
,只需将root上的所有内容重定向到/public
。NGINX没有这种可能性。
为了更清楚地说明,我可以将项目根文件夹(与公共文件夹处于同一级别)上的默认.htaccess内容传递给公共重定向
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ ^$1 [N]
RewriteCond %{REQUEST_URI} (\.\w+$) [NC]
RewriteRule ^(.*)$ public/$1
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ server.php
</IfModule>
型
在/public文件夹中还有另一个.htaccess权限
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
型
3条答案
按热度按时间3okqufwl1#
所以如果我理解正确的话,问题根本不是你的Web服务器--而是你的Laravel应用程序生成的URL,它缺少子目录?
首先你应该知道的是,Laravel不推荐或支持你用来服务多个应用的方法。
Laravel应该总是在为您的Web服务器配置的“Web目录”的根目录中提供服务。你不应该试图从“web目录”的子目录中提供Laravel应用程序。
一个更好的(并且得到适当支持的)解决方案是从子域提供服务,例如
https://my-new-project.webs.example.com/
。这可以很容易地使用您现在使用的相同方法来完成,但使用主机名而不是路径来确定要服务的应用程序。有关解析主机名组件的示例,请参见this Server Fault answer。也就是说,如果已经解决了其他所有问题,您应该能够通过简单地修复
.env
中的APP_URL
变量以包括子目录来解决生成的URL的问题。字符串
但是,我再次强烈反对这种子目录方法。它很脆弱,很可能会被Laravel代码库的更改所破坏。
x8diyxa72#
你有没有尝试为每个子目录定制ASSET_URL?
也许你可以直接在index.php文件上设置env变量:第一个月
但最好的方法是根据子目录名使用
config(['app.asset_url' => config('app.url') . $subdirectory]);
动态设置odopli943#
您可以在Nginx配置中添加额外的位置块。
字符串
^/([^/]+)
捕获项目名称(images|css|js|fonts|resources)
捕获子目录(根据需要调整)/(.*)$
捕获所请求文件的剩余路径