与Laravel 5.5相关:
在第一次安装Laravel后,我遇到了著名的“公共文件夹问题”,我想出了这个解决方案,在我个人看来,它比我在网上找到的其他解决方案更“干净”。
成就
URI中没有公共词
保护.env文件,防止好奇的人
只要使用mod_rewrite和四个简单的规则编辑.htaccess,一切都可以完成。
步骤
移动.htaccess文件到public/。Htaccess在主根目录下
编辑如下
I commented everything, so it should be clear (I hope) also to those who have never used mod_rewrite (not that I'm an expert, all the opposite). Also, to understand the rules, it must be clear that, in Laravel, if Bill connects to https://example.com, https://example.com/index.php is loaded. This file just contains the command header("refresh: 5; https://example.com/public/"), which sends the request to https://example.com/public/index.php. This second index.php is responsible to load the controller and other stuff.
# IfModule prevents the server error if the app is moved in an environment which doesn’t support mod_rewrite
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# RULES ORIGINALLY IN public/.htaccess ---
# 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]
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# --- END
# PERSONAL RULES ---
# All the requests on port 80 are redirected on HTTPS
RewriteCond %{SERVER_PORT} ^80$
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R,L]
# When .env file is requested, server redirects to 404
RewriteRule ^\.env$ - [R=404,L,NC]
# If the REQUEST_URI is empty (means: http://example.com), it loads /public/index.php
# N.B.: REQUEST_URI is *never* actually empty, it contains a slash that must be set as match as below
# .* means: anything can go here at least 0 times (= accepts any sequence of characters, including an empty string)
RewriteCond %{REQUEST_URI} ^/$
RewriteRule ^(.*) /public/index.php [L]
# If the current request is asking for a REQUEST_FILENAME that:
# a) !== existent directory
# b) !== existent file
# => if URI !== css||js||images/whatever => server loads /public/index.php, which is responsible to load the app and the related controller
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule !^(css|js|images|media)/(.*)$ /public/index.php [L,NC]
# If the current request is asking for a REQUEST_FILENAME that:
# a) !== existent directory
# b) !== existent file
# => if URI == css||js||images[=$1]/whatever[=$2] => server loads the resource at public/$1/$2
# If R flag is added, the server not only loads the resource at public/$1/$2 but redirects to it
# e.g.: bamboo.jpg resides in example.com/public/media/bamboo.jpg
# Client asks for example.com/media/bamboo.jpg
# Without R flag: the URI remains example.com/media/bamboo.jpg and loads the image
# With R flag: the server redirects the client to example.com/public/media/bamboo.jpg and loads the image
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(css|js|images|media)/(.*)$ /public/$1/$2 [L,NC]
# --- END
</IfModule>
下面的规则(原来在public/.htaccess中)可以被删除。事实上,同样的规则在最后两条规则中以更详细的方式进行了显式说明。
# Handle Front Controller...
# RewriteCond %{REQUEST_FILENAME} !-d
# RewriteCond %{REQUEST_FILENAME} !-f
# RewriteRule ^ index.php [L]
编辑:我错过了阿比纳夫·萨拉斯瓦特的解决方案,他的答案应该是公认的。只有一个简单而明确的规则,可以将所有流量重定向到公用文件夹,而无需修改任何文件。