Zend Framework custom URLs

URL organization in Zend Framework

As you may know in ZF the urls are strictly organized. First you’ve the module, if you use modules. If there is only one module, and it is normally the default one, you omit the module name from the url. Than comes the controller name, the action name in that particular controller and than separate by / the url continues with key value pairs of the get parameters.

Of course to make this all work, you’d need to setup a simple .htaccess file just to rewrite all this to the index.php file which than parses the $_SERVER[‘REQUEST_URI’] to collect all the data he need about which controller, which action and what parameters to call.

That’s pretty simple. If you’ve the following URL /user/profile/name/john.smith you may suppose that Zend Framework calls the “user” controller, “profile” action with get parameter “name” which equals to “john.smith”. In a traditional PHP style old school URL this can look like this:

?controller=user&action=profile&name=john.smith

Why I need such long URL?

The problem is that Zend reads all this, parses it and than returns the correct output. But however not always this is what we want, right? I’d like to have custom url for the profile page. Why should I need both profile and name in my URL, I’d prefer a URL like this: /user/john.smith.

But than the problem is that Zend is searching for user controller action john.smith. Such action of course doesn’t exists. Normally you cannot make all your users from the database separate actions in the user controller. That would look like fool.

FrontController plugin.

To start solving the problem I made a simple FrontController plugin. About writing FC plugins I’ve posted several posts in this blog and I’ll not mention here how to do that. Let assume I’ve the SEO plugin, which I placed in /library/Zend/Controller/Plugin/Seo.php

Thus the class I reference is Zend_Controller_Plugin_Seo. In breve the seo (what means search engine optimization) plugin contains this chunk of code:

class Zend_Controller_Plugin_Seo
       extends Zend_Controller_Plugin_Abstract
{

public function __construct($ctrl)
{
   $request = new Zend_Controller_Request_Http();
   $url = $request->getRequestUri();

   $uriComponents = explode('/', $url);
   $username = '';

   if (isset($uriComponents[2]) )
     $username = $uriComponents[2];

   if( $username ) {
      $ctrl->addRoute("user-profile",
         new Zend_Controller_Router_Route("user/:username",
            array("name" => $username,
                    "controller" => "user",
                    "action" => "profile")));

   }

Final notes!

Now I can simply register my plugin in the bootstrap.php where all my FrontController plugins are registered. The difference here is that the __construct function takes one parameter which is the FrontController instance. To do that just add this line of code in your bootstrap.php

$frontController->registerPlugin(
    new Zend_Controller_Plugin_Seo(
         $frontController->getRouter()));

and everything is fine. Now I can reference the user profile of john.smith just by writing /user/john.smith in my browser. With that technique you can also rewrite every custom url you want to work with ZF. However it is not a good practice to override everything! Remember that standard URLs in ZF helps you find quickly the controller and action you call for the current page view.

5 thoughts on “Zend Framework custom URLs

  1. There’s a much easier way to create shorter, more targetted URLs: create custom routes.

    Zend Framework provides several types of custom routes you can attach to the router, as well as an interface you can utilize to create your own. The standard routes include: “Route”, which allows you to create routes with identified placeholder segments (think: “blog/:year/:month/:day”); “Static”, for routes with no dynamic segments; “Regex”, for using regular expressions to split the route; and “Rest”, for defining routes that adhere to RESTful principles. The route interface simply asks for you to define match() and assemble() methods, which allows you to define any functionality you want.

    I highly recommend this approach over what you have blogged.

  2. Thanks for the advice! I really appreciate your recommendation which indeed defines more structured way to implement custom routes in ZF. The solution I described doesn’t pretend to be the best one, but simply another working solution. I agree it is more patch-like.

    I’d like to post another article based on the way you described.

    Thank you again!

  3. Hi Guys,

    Great tips!
    One question I’d have – we have the control panel for our custom cms which allows administrator to define keywords for each page – say you have page about_us – and administrator can also define the keyword which is displayed before the page name. Is there a way to achieve it using ZF?
    I believe that the path to each page (controller) would be generated dynamically depending on the value stored in the database.

    Any ideas how to accomplished this?

  4. Nice tutorial, I was struggling to achive such functionality since long, Worked for me!

    Thanks!!!

Leave a Reply

Your email address will not be published. Required fields are marked *