Treehouse: Grow your CSS skills. Land your dream job.

Friendly URL | GET parameters lost

  • # May 12, 2013 at 5:55 am

    Let’s say I have a website :

    And a webpage:

    I want to make it more friendly, so I use .htaccess:

    Which contains links to other “pages”. They are actually the same one, the only difference being the GET parameters from the URL, which would pull different content from the database.

    So by clicking the links within “page.php”, wether you’re on “” or “”, you’ll get to “”

    I want to make it more friendly too, so I use, again, .htaccess. The result would be “”, followed by all those values, separated by slashes: “”

    My question is: Within the page.php file, how on earth am I going to be able to make use of the GET parameters??

    $_GET[“category”] or $_GET[“page”] wouldn’t work, at least in my case. Does it work for you? It isn’t even logical to work. There is no “category” or “page” parameter in the URL. So when attempting to write $_GET[“category”], the server will analize the URL and it will need the actual parameter NAME as well as the VALUE. In our case, we only have the value. Someone, please fill me in?

    # May 12, 2013 at 6:16 am

    > $_GET[“category”] or $_GET[“page”] wouldn’t work, at least in my case. Does it work for you? It isn’t even logical to work. There is no “category” or “page” parameter in the URL.

    You can either use htaccess to rewrite the URL to what you need, or use $_SERVER to get the original URI to parse the relevant information in PHP.

    # May 12, 2013 at 6:48 am

    There are some parameters whose names I don’t want to show off in the URL. Anyway, I didn’t even know that that was possible! I should have thought of it…Thanks! Even though, I will not be able to use “isset” or “$_GET”, will I?

    # May 12, 2013 at 8:03 am

    Depends which method you use:

    RewriteRule ^/([^/]+)/([^/]+)/([^/]+)$ $1.php?category=$2&page=$3

    The above code, for example, should redirect a request of:


    I should probably clarify here, I do not approve of this particular implementation. Personally, I would redirect everything through index.php and use the REQUEST_URI session variable.

    # May 12, 2013 at 6:21 pm

    So you’re saying that in the above example, while the browser will show the user:

    It will actually be able to detect wether a parameter is set or not? Like:

    Even though we do not have the real parameter name?

    The reason for this being that, in the “back”, the users are actually on:

    And regarding your personal choice: What do you mean, more exactly, by “redirect everything through index.php”?

    # May 12, 2013 at 7:30 pm

    Well, you would need to account for items not being entered, but that’s the rough gist. In the example I posted, there would always need to be three parameters –

    What RewriteRule does is, well, rewrites URLs. You can specify what strings get rewritten. In the example I posted, I use regex to match addresses with three “subdirectories”. By using regex, I also get to take advantage of the matched items. $1 is the first item, $2 the second and $3 the third.

    A very simple rewrite is:

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    RewriteRule ^(.*)$ index.php [QSA,L]

    The first two lines say that the RewriteRule should only be applied if the address doesn’t point to an actual file or directory. This allows css, js and other files to be linked to as normal without a redirect.

    The RewriteRule uses the regex (.*) which matches everything. Every request is then sent to index.php. index.php is ALWAYS called. QSA says to append any queries to the new target. L says to stop the rewriting process and not to apply any further rules.

    The result is that a query such as:

    Is rewritten to:

    The user won’t see that. Their URL is still the pretty one. And you can access the pretty URL they entered by using $_SERVER. Some simple string handling will allow you to process that into whatever variables you need. You won’t be able to use isset($_GET[“category”])) specifically, but you can do similar operations on your parsed result.

    # May 12, 2013 at 7:41 pm

    Here’s what I do – a very similar approach:


    # if the filename is a “real” file or directory, don’t rewrite.
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    # if not, take the entire URL + query string and append it to index.php.
    RewriteRule ^.*$ index.php%{REQUEST_URI} [QSA,L]

    In php, you can get the original path the user typed with `$_SERVER` (or, on some hosts, `$_SERVER`), and the query string with `$_SERVER` (or, simply use the `$_GET` superglobal like normal).

    The difference between using `PATH_INFO` and `REQUEST_URI` (as @BenWalker suggests) is that the latter will return both the path info and the query string together (and there’s nothing wrong with that; I just find it less useful). `REQUEST_URI` will still be available to you regardless of how you rewrite the request.

    < ?php
    # example: user typed “ string”

    print $_SERVER;
    # prints “/pretty/url?ugly=query%20string”

    print $_SERVER;
    # prints “/pretty/url”

    print $_SERVER;
    # prints “ugly=query%20string”

    print $_GET;
    # prints “query string”

    # May 16, 2013 at 9:00 am

    I don’t understand. Why would you want to rewrite everything to “index.php”? Alright, as a programmer, I will still be able to get those parameters and their values. But as a user, whatever I would type, whether it’s or or I will be redirected to

    # May 16, 2013 at 9:09 am

    The request go trough index.php but the user won’t see that. It’s an easy way to make pretty urls. You only have one place in which you need to find out what the requested page was and then serve that page.

    # May 16, 2013 at 9:18 am

    > Why would you want to rewrite everything to “index.php”?

    Well, for any sort of application or larger site I will use an MVC structure of some sort. Shared code is useful, as is templating, both from a design perspective and separating the program’s logic from its final presentation.

    Do be aware that the user will never see that these redirects are happening. Their browser URLs will be the pretty ones that they entered in the first place.

    The URLs are good for users, because they are easier to remember, and for the developers they act as a bit of data to be processed by the program, rather than dictating which file on the server is executed.

    # May 16, 2013 at 9:31 am

    > You only have one place in which you need to find out what the requested page was and then serve that page.

    So I will analize the requested page right in “index.php”, and I will redirect the user to that specific page?

    # May 16, 2013 at 12:45 pm

    Pretty much, yes.

    The user is never “redirected” to a page. The page is built by the script, and depends on the URL they entered. It doesn’t matter what the files are or how they are laid out on the server. Someway, somehow your scripts need to take a user request and work out what to give back.

    That could be by having 200 individual html pages, it could be by having 1 single, mammoth PHP script, or many scripts and classes. It doesn’t matter from the user’s perspective – the results are the same from their point of view. With some clever coding, you could even move from one system to the other and they would never notice. The layout on the server is entirely about making things as easy for you as you can (and possibly some speed and security optimisations).

    That’s the summary – here’s an example (if you want it) from an application I’m currently developing:

    The Rewrite part of the htaccess:

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    RewriteRule ^(.*)$ index.php?module=$1 [QSA,L]

    Note that here I’m not fussed about pretty URLs – the only thing that needs to be memorable is the module. Eg.,, etc.

    My index.php actually doesn’t itself handle the module loading, but it could. My module class does:

    class mod {

    static function get() {
    $module = get( ‘module’, ‘home’ );
    $file = c::get( ‘root.modules’ ) . ‘/’ . $module . ‘.php’;
    return ( !file_exists( $file ) ) ? ‘home’ : $module;

    static function load( $module = ‘home’ ) {
    $file = c::get( ‘root.modules’ ) . ‘/’ . $module . ‘.php’;
    require_once( $file );
    $class = ‘mod_’ . $module;

    This uses the kirby toolkit, but not in a complicated way. All my modules are named `mod_`. `root.modules` is the path to the module directory. `get( ‘module’, ‘home’ )` is a kirby function that returns the value of `$_GET` if it is set, `’home’` if it is not. The `mod::get()` function returns the module if it is a) set; and b) a real module. Otherwise it returns `home`. `mod::load()` then requires the class file and executes `::run()`, a function that all of my modules implement.

    # May 16, 2013 at 12:55 pm

    To clarify – in this instance I don’t use any `$_SERVER` variables. This is because my URLs only include the module name in the path – everything else is in the query string. If my URLs had a variable number of properties I were expecting (such as you describe), this is when I would use `$_SERVER` or, as @traq points out, `$_SERVER`.

    # May 17, 2013 at 2:26 am

    > This is because my URLs only include the module name in the path – everything else is in the query string.

    And, in your case, what do you use to get the query string? Simply GET or SERVER variables?

    # May 17, 2013 at 5:32 am

    As I say in the post you quoted, in this instance I don’t use any $_SERVER variables. In my case, I use only the request variables (get, post and cookie). The `get()` function above takes the variable name as its first argument and returns either the value its set to, or the second argument if it isn’t set.

    However, if I were in your case, my gut feeling is that I would use `$_SERVER` like so:

    Why not try something like:

    $pathArray = explode( ‘/’, $_SERVER );
    var_dump( $pathArray );

Viewing 15 posts - 1 through 15 (of 16 total)

You must be logged in to reply to this topic.