Url Routing with PHP - Part Three

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.

Requirements

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;
  4.  
  5.       function Axial_CommandDispatcher(&$command)
  6.             {
  7.             $this->Command = $command;
  8.             }
  9.  
  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.             }
  21.  
  22.  
  23.       function Dispatch()
  24.             {
  25.             $controllerName = $this->Command->getControllerName();
  26.  
  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.             }
  8.  
  9.       function _default()
  10.             {
  11.  
  12.             }
  13.       function _error()
  14.             {
  15.  
  16.             }
  17.       function execute()
  18.             {
  19.             $functionToCall = $this->Command->getFunction();
  20.             if($this->Command->getFunction() == ")
  21.                   {
  22.                   $functionToCall = 'default';
  23.                   }
  24.  
  25.             if(!is_callable(array(&$this,'_'.$functionToCall)))
  26.                   {
  27.                   $functionToCall = 'error';
  28.                   }
  29.  
  30.  
  31.             call_user_func(array(&$this,'_'.$functionToCall));
  32.             }
  33.       }

Try it out

You can visit examples.phpaddiction.com/urlrouter/part_3/ to see it in action and download the sample code.

Conclusion

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.

Comments

16 Responses to “Url Routing with PHP - Part Three”

  1. Jon on June 16th, 2007 3:10 pm
    Gravatar

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

  2. Jon on June 16th, 2007 5:20 pm
    Gravatar

    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:
    http://site.com/users/jon/feed.rss

    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?

    Thoughts?

  3. Doug Hill on June 20th, 2007 9:43 am
    Gravatar

    Jon,
    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 on November 3rd, 2007 12:34 am
    Gravatar

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

    ie.

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

    It doesn't work

  5. Doug Hill on November 4th, 2007 9:35 pm
    Gravatar

    John:

    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 on November 6th, 2007 5:28 pm
    Gravatar

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

  7. Doug Hill on November 9th, 2007 2:39 pm
    Gravatar

    John:
    Here is a quick fix to the example.

    In Axial_UrlInterpreter change the line in the constructor from this:

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

    to this:

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

    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.

    Doug

  8. John on November 16th, 2007 6:17 am
    Gravatar

    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.

    Regards

  9. John on November 16th, 2007 12:46 pm
    Gravatar

    Hi Doug,

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

  10. Doug Hill on November 17th, 2007 3:31 am
    Gravatar

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

    Doug

  11. John on November 17th, 2007 9:11 am
    Gravatar

    Doug,
    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.

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

    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];
        showTemplate($this->Command);
        }
    
  13. John on November 17th, 2007 7:50 pm
    Gravatar

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

    echo"$params[id]";

    http://localhost/mvc/test/dostuff/id/23/page/3/sort/true

    echo"$params[id],$params[page],$params[sort]";

    so, it will prints 23,3,true

    How did you managed to get url like this http://www.phpaddiction.com/tags/php/url-routing-with-php-part-three/

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

    Regards

  14. Doug Hill on November 18th, 2007 3:11 pm
    Gravatar

    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!

    Doug

  15. Richard on February 20th, 2008 11:15 pm
    Gravatar

    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?

    Cheers

  16. Handy on April 11th, 2008 5:33 pm
    Gravatar

    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.

Leave a Reply




XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>