Bejkrools Bejkrools - 3 months ago 22
PHP Question

Riddle with routing in PHP

I made simply router with htaccess and PHP. But this way made impossible to set additional GET parametr in url.

.htaccess

RewriteEngine On
[...]
RewriteCond %{REQUEST_URI} !\.(gif|jpg|png)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?url=$1 [PT,L]
[...]


index.php

[...]
$url = isset($_GET['url']) ? $_GET['url'] : null;
$router = new Router($url);
[...]


and then i'm running dispatcher. For example url www.site.com/user/regierter runs
class UserController -> registerAction()
.But what if i want add another get request like:
www.site.com/user/regierter?layout=red.

How make it possible to dispatch url part but accept another get requests?

Answer

Your approach to rewrite isn't favorable for this use case.

It's easier to simply use the internal redirect to get the request from your webserver to PHP and let PHP deal with the request parameters.

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [PT]

This makes Apache httpd redirect any request that isn't a file or directory that exists in the document root, to index.php internally. Meaning, the redirect is completely transparent to the end-user. They see www.example.com/foo while your webserver sees /index.php and PHP just sees /foo. This makes it possible to handle the routing internally regardless of the query string parameters.

$url = $_SERVER['REQUEST_URI'];
$router = new Router($url);

Any parameters in the query string still get parsed in $_GET appropriatly. $_SERVER['REQUEST_URI'] contains the original request URI passed to PHP by your webserver such that www.example.com/foo/bar/?quix=1&quack=2 gets read by PHP as /foo/bar/?quix=1&quack=2 and $_GET['quix'] == 1 and $_GET['quack'] == 2.

So the original query string (i.e. the HTTP request line) remains untouched as far as PHP can tell. The only change made here is in how your web server determines whether to let PHP handle a request or to serve it up directly from the document root.

Now your router can extract all the information it needs from $_SERVER['REQUEST_URI'] directly, with something like parse_url, for example.

So if the request was made to www.site.com/user/register?layout=red var_dump(parse_url($_SERVER['REQUEST_URI'])) would give you something like this.

array(2) {
  ["path"]=>
  string(14) "/user/register"
  ["query"]=>
  string(10) "layout=red"
}

And $_GET['layout'] will still give you "red".