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.

From stoimen.com

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s