Laravel 如何处理 url-重写?

How Laravel handle url-rewriting?

出于好奇... Laravel 框架如何捕获 "get" 参数?

我刚打开他们的.htaccess,发现如下内容:

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/$ / [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}]
</IfModule>

请注意,在这部分中,根本没有传递给 index.php 的参数

# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

最常见的情况是这样的:

RewriteRule ^(.*)$ index.php?getparams= [L]

使用RewriteRule时,主要有两种操作形式:内部重定向和外部重定向。

外部

使用 [R] 标志的外部重定向将告诉您的浏览器重定向到新的 URL,例如

RewriteRule ^foo bar/ [L,R=PERMANENT]

会告诉浏览器"the content located at /foo can actually be found at /bar, please redirect the user"。然后浏览器发出一个新的 /bar 请求,该请求从头开始处理。使用该方法时,需要保留查询字符串参数,一般使用QSA标志,如

RewriteRule ^foo bar/ [L,R=301,QSA]

如果它们没有传递给新请求,它们就会丢失。

内部

另一方面,内部重定向不会将任何有关重定向的信息发送回浏览器。他们只是告诉 Apache 任何匹配 URL 的请求都应该由给定的文件处理。所以

RewriteRule ^ index.php [L]

来自 Laravel 的示例指示 Apache 所有请求都应由 index.php 脚本(Laravel 前端控制器)处理。作为原始请求的一部分,查询字符串仍可在 PHP 中访问,未更改。

Laravel 本身然后使用 PHP 超全局变量($_GET$_POST 等)来填充 Illuminate\HTTP\Request 对象,通常随后使用在整个应用程序中封装对原始请求的访问,例如

# HTTP Request = /?foo=bar
echo $request->get('foo');
// "bar"

这不是 Laravel 具体的,而是 PHP 框架如何处理它。

首先,无需向 index.php 添加查询字符串,因为它已经隐式存在。参见 RewriteRule

...
Modifying the Query String

By default, the query string is passed through unchanged. You can, however, create URLs in the substitution string containing a query string part. Simply use a question mark inside the substitution string to indicate that the following text should be re-injected into the query string. When you want to erase an existing query string, end the substitution string with just a question mark. To combine new and old query strings, use the [QSA] flag.

@iainn 已经提到了超全局 $_GET$_POST。还有 $_SERVER,其中包含 - 除其他外 - REQUEST_URIPATH_INFO。有了这些,您可以获得请求的 URL 而无需将其作为查询字符串的一部分显式传递。