Url Routing with PHP – Part Three

Posted by:

In the final part of this series, I will build a functional modular front controller that can be easily adapted to small projects. It is basically the “C” in MVC for a simple MVC framework. If you haven’t read the first two articles I recommend that you read over them first. Url Routing with PHP – Part One and Url Routing with PHP – Part Two.


  • Apache with mod_rewrite enabled
  • PHP

A few changes

If you have followed along with the series you will see a few changes to the code that I left you with in Url Routing with PHP – Part Two. The Axial_URLInterpreter and the Axial_Command object received a few minor changes suggested via comments on the previous articles. Most of the changes are in the Axial_CommandDispatch class. A new class Axial_Controller is introduced in this article, along with some changes to the directory structure.

Dispatch via convention

Using a front controller allows creation and access to controllers in a standard way. By using a consistent naming convention and directory structure, command objects can be dispatched via a generic piece of code. When a command is dispatched the appropriate controller is loaded and its execute() method called.

  1. class Axial_CommandDispatcher
  2.       {
  3.       var $Command;
  5.       function Axial_CommandDispatcher(&$command)
  6.             {
  7.             $this->Command = $command;
  8.             }
  10.       function isController($controllerName)
  11.             {
  12.             if(file_exists(‘axial/controllers/’.$controllerName.‘/controller.’.$controllerName.‘.php’))
  13.                   {
  14.                   return true;
  15.                   }
  16.             else
  17.                   {
  18.                   return false;
  19.                   }
  20.             }
  23.       function Dispatch()
  24.             {
  25.             $controllerName = $this->Command->getControllerName();
  27.             if($this->isController($controllerName) == false)
  28.                   {
  29.                   $controllerName = ‘error’;
  30.                   }
  31.             include(‘axial/controllers/’.$controllerName.‘/controller.’.$controllerName.‘.php’);
  32.             $controllerClass = $controllerName."Controller";
  33.             $controller = new $controllerClass($this->Command);
  34.             $controller->execute();
  35.             }
  36.       }

As you can see from the code above on line 31, the controller must reside in a directory under ‘axial/controllers/controllername and be named using the convention controller.controllername.php.

The Controller

All controllers must descend from the base class Axial_Controller. The execute() function in the base class searches for the function passed in the Axial_Command object prepended with a ‘_’ within the controller, if this method is found it is executed if it is not found the _error() function is called, if no function is specified the _default() function is called.

  1. class Axial_Controller
  2.       {
  3.       var $Command;
  4.       function Axial_Controller(&$command)
  5.             {
  6.             $this->Command = $command;
  7.             }
  9.       function _default()
  10.             {
  12.             }
  13.       function _error()
  14.             {
  16.             }
  17.       function execute()
  18.             {
  19.             $functionToCall = $this->Command->getFunction();
  20.             if($this->Command->getFunction() == )
  21.                   {
  22.                   $functionToCall = ‘default’;
  23.                   }
  25.             if(!is_callable(array(&$this,‘_’.$functionToCall)))
  26.                   {
  27.                   $functionToCall = ‘error’;
  28.                   }
  31.             call_user_func(array(&$this,‘_’.$functionToCall));
  32.             }
  33.       }

Try it out

You can visit to see it in action and download the sample code.


If you look at the index.php from the sample code in the second part in the series you will see that the code is virtually unchanged from this version. The main change is in the Axial_CommandDispatcher class and with the addition fo the Axial_Controller class I have build a pluggable extendable front controller based framework. Take a look at the example page and code to get a feel for what you can do with this mini framework.

When I began this series I left out any discussion of the view portion of MVC since it was beyond the scope of the title and what I intended to discuss, I discovered though that in order to build any further on the front controller portion of the framework I would need to introduce that concept. So I’m going to stop this series here and will pick it up again later together with a more fitting title and topic.


About the Author


  1. Jon  June 16, 2007

    Anyone know how to get CheckSpelling On to work with this URL routing?

  2. Jon  June 16, 2007

    I'm using URL routing to display a user's rss feeds. However, these feeds are physically stored in a separate directory.

    So when someones goes to say:

    The URL rounting parses the /users/ /jon/ and feed.rss and currently redirects to the physical location of the .rss feed.

    Is there a way to mask the URL switch so when someone goes to that .rss link it appears as if the folder and file do in fact reside in the that directory?

    Or perhaps I should read the .rss and output it?


  3. Doug Hill  June 20, 2007

    I think the most flexible solution would be to read the .rss and output it. Thats probably the way I would go. I suppose it all depends on the situation.

    If you are doing the redirect I'm assuming the feeds are pre-generated, why not just place the feeds in the physical directory you want the url to mimic and skip the redirect. If the physical location is /users/jon/feed.rss and you use this as the actual URL then the .htaccess is going to bypass the url routing anyway since the file exists.

  4. John  November 3, 2007

    Hi, How will i get parameter from default or any function?


    2. function _default(){
    3.  $id= intval($_GET["id"]);
    4.  echo"id $id";
    5. }

    It doesn't work

  5. Doug Hill  November 4, 2007


    Look back at part two of the series. I'll post a longer reply later I'm a bit constrained for time today.

  6. jerkan  November 6, 2007

    what if you wanna show something from a controller and another thing from another controller?

  7. Doug Hill  November 9, 2007

    Here is a quick fix to the example.

    In Axial_UrlInterpreter change the line in the constructor from this:

    2. $requestURI = explode('/', $_SERVER['REQUEST_URI']);

    to this:

    2. $tempRequestURI = str_replace('?'.$_SERVER['QUERY_STRING'],",$_SERVER['REQUEST_URI']);
    3. $requestURI = explode('/', $tempRequestURI);

    This will remove the query string so routing works correctly and leave the $_GET variable intact.

    I have an entirely new version of code for this series, guess I should get to posting soon.


  8. John  November 16, 2007

    Thanks Doug. I will try your code. Your tutorial is very help.
    I want use simple framework instead of larger framework such as phpcake or codeigniter.
    Keep up the good work.


  9. John  November 16, 2007

    Hi Doug,

    I tried your above code and it's not working.

  10. Doug Hill  November 17, 2007

    John, could you drop me some code on email or here to show me what the problem is?


  11. John  November 17, 2007

    I've downloaded files from from this tutorial then simply called it through browser http://localhost/mvc/test/dostuff/id/23/. I want to get id from this url.

    3.         function _error()
    4.             {
    5.             showErrorTemplate($this->Command);
    6.             }
    7.         function _dostuff()        
    8.             {
    9.              echo"id=$_GET[id]";
    10.              showTemplate($this->Command);
    11.             }
    13. }
  12. Doug Hill  November 17, 2007

    I think I see what the problem is. If you just want the parameters to the function from the url as formatted like your example http://localhost/mvc/test/dostuff/id/23/ you would use $this->Command->getParameters() to access them as an array instead of the $_GET[] variable.

    If you want to actually get them from $_GET[] you would have to format your URL like http://localhost/mvc/test/dostuff/?id=23 and use the changes to the code i posted before.

    function _dostuff()
        $params =  $this->Command->getParameters();
        echo $params[0].': '.$params[1];
  13. John  November 17, 2007

    Thank you Doug. It would be great if we could get/post/request parameter value by calling its name.




    so, it will prints 23,3,true

    How did you managed to get url like this

    Did you use MVC method or it is done using .htaccess ?


  14. Doug Hill  November 18, 2007

    John if you look at the Axial_UrlInterpreter class you will see that you can modify how the url is transformed into a command object. Instead of the way I did it you could make it handle the parameters as key => value pairs… or any other way you want. If i get a little time this week i'll write a new article that covers this.

    The urls in the blog come from wordpress not my doing!


  15. Richard  February 20, 2008

    Hi Doug, nice tutorial btw, really clarified MVC for me. I've been using on open source MVC framework and I'm looking to build my own now :) Anyway one thing that did demystify me in your tutorial is models – where are they? Could you illustrated within your sample code how you could implement one?


  16. Handy  April 11, 2008

    Thank you for the tutorial. Zend framework provides also a very good frontcontroller. So it might be a help to understand the functionality and build own frontcontroller.

  17. zsolt sandor  December 4, 2008


    a nice tutorial, ad the first url router witch works on all servers / a least on those teht i tried /

    should be the exampleutils.php the model?

  18. vulo  October 5, 2009

    Hi, I have problem with the url router, as it reload 2 3 times before to load the page, of course it is too fast for a normal use to see it, but I include mail sending of every execution of the url-array.

    I receive that these values are loaded into the url array before the actual data from the URL is loaded

    /not the same every time/

    and then
    the actual URL parameter – 'event' or 'contacts'
    I am using some session messages, that's how i find this "bug".

    Has anyone have ides, why this is happening.
    Thanks in advance

  19. B@stian  May 25, 2011

    I am wondering what the '&' before $command means?
    for example you are using it here:
    function Axial_CommandDispatcher(&$command)
    and function Axial_Controller(&$command)

    Could you please explain it ?


  20. Doug Hill  June 8, 2011

    The & sign denotes a pass by reference variable.


  21. sike  July 8, 2011

    Thank you very much for these articles and I do hope you continue the series -I have found them very useful

  22. Tai Sheppard  October 5, 2011

    This is exactly what I was looking for. I needed a dispatcher class that would pass url cruft as variable intact to the methods in the class.

    One thing that isn't correct though is that you need to test the class for the called method and then adjust the command parameters so that dispatcher doesn't mistake a parameter for the method.

    This way you can call the default method with parameters which you can't do with the script as you have it posted here.

    If you call /test/param1/param2/param3 for instance, the dispatcher will use param1 as your method. Simply test the controller for the method using method_exists() and if it fails, array_unshift() to add param1 to your existing parameters.

    Otherwise … KILLER job Doug, thanks a bunch.


  23. Rudi  July 14, 2012

    Hi Doug,

    I just wanted to say thank you for the series on this topic. I have been scouring the internet to find something more in-depth on re writing and a re write engine and this is the closest thing I could find and it has given me a great starting point.

    I will be using this on my project shorty

    Thanks once again!

  24. Robert  August 21, 2012

    I'm working on my own framework which does the routing but I'm having issues with setting 404 headers. It will work on the requested page but if the page is valid and the css files are not the css files will show as 200 ok and not 404. Can you do a 4th part that will do proper 404 headers for files?

  25. Luis  September 5, 2012

    So, There's no way to remove "/root/" from the URL string, unless I'm calling the default controller and no function? What if i have another function that has to be executed inside "root"? The only way I have found to eliminate "root" from the URL string is this: (it shows a series of numbers from 13 to 26)

    See the double slash between "router" and "listdata"? That makes me nervous. What should I do to eliminate this ugliness?

    Thanks for sharing

  26. wilfredo  June 15, 2014

    Dude this opened my mind, thx a lot for the tutorial, this helped me to build my own clases, router and controllers, now ill try to build models with the same concept. Also you need to put links on your tutorials, in the first part i was lost, there is not a "click here for next part", and in the secction "related post" was empty. i have to search in all the web page, or change the url "part-one" to "part-two"

  27. click this link now  July 18, 2014

    Hi all, here every person is sharing these experience, so it's pleasant to read this web site, and I used to go to see this webpage daily.

  28. best kitesurfing kites 2014  July 23, 2014

    Thanks for finally writing about >Url Routing with PHP – Part Three ? phpaddiction <Liked it!

  29. bodybuilding hgh side effects  July 24, 2014

    This post is genuinely a fastidious one it helps new net users, who are wishing in favor of blogging.

  30.  August 18, 2014

    I like the helpful info you provide in your articles. I'll bookmark your weblog and check
    again here frequently. I'm quite certain I will learn lots of new stuff right
    here! Best of luck for the next!

  31. ????? ???? ??????  September 10, 2014

    Link exchange is nothing else except it is just placing the other person's webpage link on your page at appropriate
    place and other person will also do same for you.

  32.  October 13, 2014

    I gott this website from myy friend who tod me
    concerning tis web site and now this time I am browsing this web site and reeading very informative content here.

  33. Sallie  November 11, 2015

    Thank you for the good writeup. It in truth was a amusement account it.
    Glance complex to more introduced agreeable fom you!
    By the way, how can we keep inn touch?

  34. jelq funciona  December 5, 2015

    This paragraph is genuinely a nice one it assists new the web users,
    who are wishing in favor of blogging.

  35. business card printing  December 5, 2015

    After going over a number of the blog posts on your
    web page, I really like your technique of blogging. I added it to my bookmark site
    list and will be checking back soon. Please check out my web site
    as well and tell me how you feel.

  36. luxury christmas wreath  December 9, 2015

    Hello there, You have done an incredible job.

    I'll definitely digg it and personally suggest
    to my friends. I'm sure they will be benefited from this web site.

  37.  December 9, 2015

    Good blog you've got here.. It's difficult to find high quality
    writing like yours these days. I truly appreciate people like you!
    Take care!!

  38.  December 10, 2015

    Hey! I'm at work browsing your blog from my new iphone!
    Just wanted to say I love reading through your blog and look forward
    to all your posts! Carry on the excellent work!

  39. Moises  December 10, 2015

    Good day I am so happy I found your blog page, I really found you by mistake, while I was looking on Bing for something else, Anyhow I am here now and would just like to say thank you for a marvelous post and a all round entertaining blog (I also love the theme/design), I don’t
    have time to read it all at the minute but I have saved it and also
    added your RSS feeds, so when I have time I will
    be back to read more, Please do keep up the fantastic jo.

  40.  December 17, 2015

    Hello there, You've done an incredible job. I will definitely digg it and personally suggest too my friends.
    I amm confident they'll be benefited from this website.

  41. ofertas hoteles en benidorm baratos  January 15, 2016

    Bancosol Alimentos y NH Hoteles firman un acuerdo de colaboración para
    la inserción laboral de personas en riesgo de exclusión social.
    Tree House , ubicado en el Refugio Nacional de Vida Silvestre Gandoca-Manzanillo de Los hoteles Trump son solo la última adición a una lista, cada vez
    más larga, de compañías que han sido hackeadas.

  42. ???? ?????? ???? ???  March 2, 2016

    Magnificent beat ! I would like to apprentice while you amend your site, how could i subscribe for
    a blog website? The account aided me a acceptable deal.
    I had been tiny bit acquainted of this your broadcast provided bright clear idea

  43.  May 19, 2016

    If you have a car that is still in production (within the
    previous 20 years) and isn't really a custom-made ignition assembly it will be much easier to find a business to set you brand-new car secrets or help you with OEM or aftermarket part replacements.

  44. ?????  June 4, 2016

    Truly no matter if someone doesn't be aware of then its
    up to other visitors that they will help, so here it

  45. cerrajeros puertas acorazadas  June 7, 2016

    Hola!! estuve leyendo asi como unas 4 horas en la
    nube hoy y no pude imaginar leer nada tan increible como tu post.
    Me ha exclamado mucho la forma que posees al escribir y
    que es lo que me ha llegado. A mi manera de
    ver esto, si un porcentaje alto redactores usaran este
    tipo de comentarios, Internet seria mucho mas practico.
    Espero que vayas por estos lares y siga disfrutando textos
    de la fuerza que tiene este.

  46. bao cao su  August 12, 2016

    This post is in fact a nice one it helps new web viewers, who
    are wishing in favor of blogging.

Add a Comment