0

I'm just new with Zend and I have a little trouble with Zend Routers. I've searched about it, but nothing found...

I want to be able to define a router for each defined variable at uri level to point to a different action in one controller.

I'm working with lang and modules so I defined at bootstrap application the next initRoutes function:

protected function _initRoutes()
{
    $front = Zend_Controller_Front::getInstance();
    $router = $front->getRouter();

    $defaultRoute = new Zend_Controller_Router_Route(
        ':lang/:module/:controller/:action',
        array(
            'lang' => 'es',
            'module' => 'default',
            'controller' => 'index',
            'action' => 'index'
        ),
        array(
            'lang' => '^(en|es)$',
            'module' => '^(default|admin)$'
        )
    );

    $router->addRoute('defaultRoute', $defaultRoute);

    return $router;
}

I want to be able to access forum sections and forum topics by their defined action.

Something like :

  • mydomain/forum -> forum/index

  • mydomain/forum/section -> forum/sectionAction

  • mydomain/forum/section/topic -> forum/topicAction

and also with the lang and module defined at uri level like :

  • mydomain/lang/module/forum

  • mydomain/lang/module/forum/section

  • mydomain/lang/module/forum/section/topic

So I have this :

class ForumController extends Zend_Controller_Action
{

public function indexAction()
{
}

public function sectionAction()
{
}

public function topicAction()
{
}

Then I created the next routes inside the Default_Bootstrap :

$forumRoutes = new Zend_Controller_Router_Route(
    ':lang/:module/forum',
    array(
        'lang' => 'es',
        'module' => 'default',
        'controller' => 'forum',
        'action' => 'index'
    )
);

$sectionRoutes = new Zend_Controller_Router_Route(
    ':lang/:module/forum/:section',
    array(
        'lang' => 'es',
        'module' => 'default',
        'controller' => 'forum',
        'action' => 'section',
        'section' => ''
    )
);

$topic = new Zend_Controller_Router_Route(
    ':lang/:module/forum/:section/:topic',
    array(
        'lang' => 'es',
        'module' => 'default',
        'controller' => 'forum',
        'action' => 'topic',
        'section' => '',
        'topic' => ''
    )
);

$router->addRoute('forumTopics', $topic);
$router->addRoute('forumSections', $section);
$router->addRoute('forum', $forumRoutes);

Now, this only works if I define the lang and module at uri level, but doesn't work if I defined like => mydomain/forum/section | section/topic. This also brings me another problem with my navigation->menu. If I define "forum" as a static variable at router definition, when I hover over at any label defined at navigatoin.xml, the uri level have the same value for every one of them.

I've tried to make a chain like this:

    $forumRoutes = new Zend_Controller_Router_Route(
        ':lang/:module/forum',
        array(
            'lang' => 'es',
            'module' => 'default',
            'controller' => 'forum',
            'action' => 'index'
        )
    );

    $section = new Zend_Controller_Router_Route(
        ':section',
        array(
            'action' => 'section',
            'section' => ''
        )
    )

    $topic = new Zend_Controller_Router_Route(
        ':topic',
        array(
            'action' => 'topic',
            'topic' => ''
        )
    )

    $chainedRoute = new Zend_Controller_Router_Route_Chain();
    $chainedRoute->chain($topic)
                 ->chain($section)
                 ->chain($forumRoutes);
    $router->addRoute($chainedRoute);

But this doesn't work as I expected.

Any help would be appreciated, thanks.

Tiago Farias
  • 3,397
  • 1
  • 27
  • 30
Ramiro
  • 1
  • 3

2 Answers2

2

You are new to Zend. You said it. So here are some explanations:

  1. Ideally the URL on Zend application is:

example.com/controller/action/param-name/:param-value

So in which case, if there is an action called Edit under UsersController, it will be:

example.com/users/edit

if action is add, it will be :

example.com/users/add

when you specify first parameter as a variable, it will collide with controller requests. Example: if you say controller is User but first parameter accepts a value and puts it in emplyees then a request as example.com/employees and example.com/user will both point towards employees controller even if the usercontroller exists! which again is a theory!

What you might want to do is, leave the routes to only accept dynamic values rather routing! You do not want users to route your application but, route user to different sections of the application.

About language then you need to use Zend_Locale which will check for HTML language that is

<html lang="nl"> or <html lang = "en">

Hope things are clear! :)

Keval Domadia
  • 4,768
  • 1
  • 37
  • 64
  • Oh i see, thanks for the reply, but the thing I want to do is: Depend on how many parameters I have on the URI, the Controller_Action I will use to render. So I can define at router level that if the forum controller gets the first parameter will be rendered with the "sectionAction" and if I've two parameters I will render with the "topicAction" where I only have to do something like `public function sectionAction() { $section = $this->_request->getParam('section'); //@TODO : get from Db and render }` Is that possible to be done with Zend_Controller_Router? – Ramiro Aug 15 '12 at 19:38
  • I done something like that in codeIgniter, where on the routes config I set an Array like `$routes['forum/(a-z)'] = 'forum/section'` and to match the second parameter just add a new router filter like : `$routes['forum/(a-z)/(a-z)'] = 'forum/topic'` Is that possible to match with Zend Routers? like a redirect, but only get the uri parameters and redirect to the needed action. – Ramiro Aug 15 '12 at 20:06
  • Codeigniter uses segment based check whereas zend checks for the request! so there is no such thing as 'segment' but, u fetch things using Request-Param... Here, as I mentioned you will have to re-plan the application... actions come under controllers... Example, Users controller can have view,add,amend,delete.. routes are used for example routes - "my-dashboard" which routes to User controller - tools and options action... Cool? – Keval Domadia Aug 15 '12 at 21:27
  • Oh I see, you've solved a big problem. Thanks, I will back to read about goals of zend routers – Ramiro Aug 16 '12 at 02:41
  • in that case, how about clicking on the tick, right next to my answer? :D – Keval Domadia Aug 16 '12 at 03:19
1

Here's a quick example which should help you work with routes like that in ZF.

If you are using a default project structure like the one you get when starting a new project using Zend Tool go into the Application folder.

In your Bootstrap.php set up something like this:

protected function _initRouteBind() {
        // get the front controller and get the router
        $front  = Zend_Controller_Front::getInstance();
        $router = $front->getRouter();
        // add each custom route like this giving them a descriptive name 
        $router->addRoute(
            'addTheDescriptiveRouteNameHere',
            new Zend_Controller_Router_Route(
                '/:controller/:id/:action/:somevar',
                array(
                    'module'     => 'default', 
                    'controller' => ':controller',
                    'action'     => ':action', 
                    'id'         => ':id',
                    'somevar'    => ':somevar'
                )
            )
        );   
}

My example above is just to illustrate how you would use a route where the controller, the action and a couple of parameters are set in the url.

The controller and action should be resolved without any additional work however to get the 'id' or 'somevar' value you can do this in your controller:

public function yourAction()
{
    // How you get the parameters to pass in to a function
    $id = $this->getRequest()->getParam('id');
    $somevar = $this->getRequest()->getParam('somevar');

    // Using the parameters
    $dataYouWant = $this->yourAmazingMethod($id);
    $somethingElse = $this->yourOtherAmazingMethod($somevar);

    // Assign results to the view
    $this->view->data = $dataYouWant;
    $this->view->something = $somethingElse;
}     

So while you will want to make sure your methods handle the parameters being passed in with care (after all it is user supplied info) this is the principle behind making use of the route parameter binding. You can of course do things like '/site' as the route and have it direct to a CMS module or controller, then another for '/site/:id' where 'id' is a page identifier.

Also just to say a nice alternative to:

$id = $this->getRequest()->getParam('id');
$somevar = $this->getRequest()->getParam('somevar');

which wasn't that nice itself anyway since it was assuming a parameter was going to be passed, using shorthand conditional statement in conjunction with action helpers is:

$id = ($this->_hasParam('id')) ? $this->_getParam('id') : null;
$somevar = ($this->_hasParam('somevar')) ? $this->_getParam('somevar') : null;

If you are not familiar with this, the

($this->_hasParam('id'))

is the conditional test which if true assigns the value of whatever is on the left of the ':' and which if false assigns the value of whatever is on the right of the ':'.

So if true the value assigned would be

$this->_getParam('id')

and null if false. Does that help? :-D

dkcwd
  • 569
  • 3
  • 9