0

Just for curiosity... How Laravel framework captures "get" parameters?

I just opened their .htaccess and found the content bellow:

<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 ^(.*)/$ /$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}]
</IfModule>

Note that in this part, there is no parameter being passed to index.php at all

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

The most common scenario would be something like:

RewriteRule ^(.*)$ index.php?getparams=$1 [L]
CarlosCarucce
  • 3,420
  • 1
  • 28
  • 51

2 Answers2

2

When using RewriteRule, there are two main forms of operation: internal and external redirects.

External

External redirects, which uses the [R] flag, will tell your browser to redirect to a new URL, e.g.

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

will tell the browser "the content located at /foo can actually be found at /bar, please redirect the user". The browser then issues a new request for /bar, which is processed from scratch. When using this method, query string parameters need to be preserved, generally by using the QSA flag, e.g.

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

If they are not passed through to the new request, they are lost.

Internal

Internal redirects on the other hand, don't send any information about the redirect back to the browser. They're simply telling Apache that any requests matching the URL should be handled by the given file. So

RewriteRule ^ index.php [L]

from the Laravel example is directing Apache that all requests should be handled by the index.php script (the Laravel front-controller). The query-string is still accessible in PHP as part of the original request, which hasn't been changed.

Laravel itself then uses the PHP superglobals ($_GET, $_POST, etc) to populate an Illuminate\HTTP\Request object, which is generally then used throughout the application to encapsulate access to the original request, e.g.

# HTTP Request = /?foo=bar
echo $request->get('foo');
// "bar"
iainn
  • 16,826
  • 9
  • 33
  • 40
  • I found a method (`createFromGlobals`) in `Symfony\Component\HttpFoundation\Request` class, that, as you said, read the values from php superglobals. But I made a simple test using the same htaccess file, just a `print_r($_REQUEST)`, that is returning an empty array. – CarlosCarucce May 24 '16 at 14:26
  • Not sure why that wouldn't work, I've just tried the same and `$_REQUEST` is populated correctly. Perhaps Apache isn't configured to read .htaccess files in that directory? The `AllowOverride` parameter might need to be set. – iainn May 24 '16 at 14:42
  • AllowOverride is set to **All** on my local server. Can you send your test somewhere? – CarlosCarucce May 24 '16 at 14:51
  • It's literally just a directory with the exact .htaccess from your question and a one-line index.php file with `print_r($_REQUEST);` – iainn May 24 '16 at 15:10
  • I am calling it as: `http://localhost/test/param1/param2`, where `param1/param2` is the query string – CarlosCarucce May 24 '16 at 16:12
  • 1
    Ah ok, I see the confusion. That doesn't contain a query string, so it'll be available under `$_SERVER['REQUEST_URI']` instead. But looks like you already saw that on the other answer. – iainn May 24 '16 at 18:39
  • Yes. Thank you for the help anyway. That was simpler than expected – CarlosCarucce May 24 '16 at 19:10
1

This is not Laravel specific, but how any PHP framework handles it.

First, there's no need to add a query string to index.php, because it is already there implicitly. See 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 already mentioned the superglobals $_GET and $_POST. There's also $_SERVER, which contains - among many others - REQUEST_URI or PATH_INFO. With these, you can get at the requested URL without passing it explicitly as part of the query string.

Community
  • 1
  • 1
Olaf Dietsche
  • 72,253
  • 8
  • 102
  • 198