我的目录结构是这样的:
vhostrootdir/
|- app/
|- public/
|- css/
|- img/
|- js/
这是我的重写:
ServerName vhostname
<Directory "vhost/root/dir">
Options FollowSymLinks
AllowOverride None
Require local
RewriteEngine On
RewriteCond %{CONTEXT_DOCUMENT_ROOT}/public/$1 -f
RewriteRule ^((?s).*)$ public/$1 [END]
RewriteRule ^((?s).*)$ index.php?_url=$1 [END]
</Directory>
如果我去vhostname/whatever
,然后我的php $_GET["_url"]
返回whatever
和地址栏保持vhostname/whatever
,如所需。
然而,如果我去vhostname/public
,那么$_GET["_url"]
是public/
。注意这个额外的'/',尽管这并不困扰我。问题是浏览器地址栏也改变为 vhostname/public/?_url=/public
,这是我绝对不想要的。
为了增加混乱,如果我去vhostname/public/
(注意额外的'/'),那么它可以正常工作。我得到$_GET["_url"]
是public/
和地址栏没有改变。
如果我转到vhostname/app
,情况也是一样的。
Edit:原来是浏览器历史记录问题。我清除了Chrome的历史记录,这就解决了问题。没关系,这并没有解决它。在将DocumentRoot更改为公共文件夹后,它仍然发生在公共和应用程序url上,但随后清除历史记录,它不再发生在它们上,现在正在公共文件夹子文件夹上发生。
注意,你需要把DocumentRoot指向public/,因为app/不应该通过web访问。
在本例中,设置空路径将导致_url == none,否则_url将包含添加的任何路径。
ServerName vhostname
DocumentRoot /vhost/root/dir/public
<Directory "/vhost/root/dir/public">
AllowOverride none
Require local
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^$ index.php?_url=none [NC,QSA,L]
# we need to serve static files
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# pass the path to _url
RewriteRule ^(.+)$ index.php?_url=$1 [NC,QSA,L]
</IfModule>
好的,我想我已经找到问题所在了。因为重写之前的URL是解析到一个目录的,而且我省略了末尾的/
,所以apache自动发送了一个301 Moved permanent重定向,并添加了末尾的/
。我猜由于apache做事情的顺序,重定向也拾取了重写,而不是301重定向从http://<vhostname>/img
到<vhostname>/img/
,它是301重定向到<vhostname>/img/?_url=img
。
我终于解决了这个问题(我认为),通过添加DirectorySlash off
到我的vhost。