5

This should be really simple, but I want to be able to use the url as a variable like the php frameworks do.

mywebsite.com/hello-world

I want my index.php to see "hello-world" as a variable and I want index.php to load. Is this done through php or do I have to use a htaccess file?

Many php frameworks use urls to send a message to the index file... for example...

mysite.com/controller/view

How would I route these myself via php?

A little help?

3 Answers 3

3

There are 2 steps:

  1. Rewrite the url using an .htaccess file (on linux). You need to make sure all requests go to your php file so you will need to rewrite all requests to non-existing files and folders to your php file;
  2. In your php file you analyze the url (using for example $_SERVER['REQUEST_URI']) and take action depending on its contents.

For step 1. you could use something like:

RewriteEngine On
RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ your_file.php?url=$1 [L,QSA]

And then in your php file in step 2. you have the requested url in $_GET['url'].

Edit:

If you want to rewrite only certain sub-directories, you could also use a rule like:

RewriteRule ^sub/dir/to/rewrite/(.*)$ your_file.php?url=$1 [L,QSA]

Some details:

  • ^(.*)$ captures everything (all characters) between the start ^ and the end $. They are captured using the parenthesis so that you can use them in the query string like $1. In the edited example, only the section after ..../rewrite/ gets captured;
  • The options between [ ... ] mean that it is the L Last rule to process and QSA that the original query string is also added to the new url. That means that if your url is /hello-world?some_var=4 that the some_var variable gets appended to the rewritten url: your_file.php?url=hello-world&some_var=4.
Sign up to request clarification or add additional context in comments.

6 Comments

Is there a way to have it not go to the root directory without specifying the root directory but have it rely on where the .htaccess file is? I hope that made sense... I have my index.php file located in a sub directory.
@Joseph I think you have to specify the root directory with RewriteBase; I don't think you can tell Apache to set RewriteBase dynamically based on the location of the .htaccess file.
@Joseph See my edit. But you can either analyze the query string or the original url (like I mentioned at the top), there is not much difference.
@MattBrowne Ok, another quick question... What is the point of "^(.*)$" verses the way that you and the other answers have written it. Also what does "[L,QSA]" do?
@Joseph ^(.*)$ allows the URL to be set as a GET parameter (where @jeroen has url=$1), which can be convenient, but either way works. Since you're dealing with subdirectories you're probably better off with @jeroen's version. Not sure about [L,QSA]; I've been copying that from others to be honest ;)
|
1

This sort of rerouting must be done on the webserver level, either in the Apache config files for your server or (more likely) through an .htaccess file.

This is the .htaccess file I use on my own site to do this sort of re-routing:

# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f

#Route everything else through index.php
RewriteRule .* index.php/?$0 [PT,L]

Then in index.php I look up the URLs in my database to pull the page content:

if(isset($_SERVER['REQUEST_URI']) and strlen($_SERVER['REQUEST_URI']) > 1)
    $requested_url = substr($_SERVER['REQUEST_URI'], 1);
else
    $requested_url = 'home';

Comments

1

What you want to achieve is called the "Front Controller" pattern. It's usually done with the use of Apache's mod_rewrite. Without URL rewriting you can still do something similar, but your URLs would look like this:

mysite.com/index.php/controller/view

Instead of: mysite.com/controller/view as you want.

Here's a minimal .htaccess file to do the URL rewriting:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]

Then you parse the URL from $_SERVER['REQUEST_URI'] but remember to strip off any GET parameters at the end when determining the view name.

I personally wanted something like this recently without a full-fledged framework so I used this micro-framework just to do the routing, and it worked very nicely:

http://www.slimframework.com/

Then you can write your own controller class and set up the routing; here's the code I used:

$app = new \Slim\Slim();

$app->map('/:controller(/:action)', 'dispatchControllerAction')
    ->via('GET', 'POST');

function dispatchControllerAction($controllerName, $action='index') {
    //multi-word controllers and actions should be hyphen-separated in the URL
    $controllerClass = 'Controllers\\'.ucfirst(camelize($controllerName, '-'));
    $controller = new $controllerClass;
    $controller->execute(camelize($action, '-'));
}

/**
 * Adapted from the Kohana_Inflector::camelize function (from the Kohana framework)
 * Added the $altSeparator parameter
 * 
 * Makes a phrase camel case. Spaces and underscores will be removed.
 *
 *     $str = Inflector::camelize('mother cat');     // "motherCat"
 *     $str = Inflector::camelize('kittens in bed'); // "kittensInBed"
 *
 * @param   string  $str    phrase to camelize
 * @param   string  $altSeparator  Alternate separator to be parsed in addition to spaces. Defaults to an underscore.
 *      If your string is hyphen-separated (rather than space- or underscore-separated), set this to a hyphen
 * @return  string
 */
function camelize($str, $altSeparator='_')
{
    $str = 'x'.strtolower(trim($str));
    $str = ucwords(preg_replace('/[\s'.$altSeparator.']+/', ' ', $str));

    return substr(str_replace(' ', '', $str), 1);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.