开发者

Zend Framework Router dynamic routes

I bumped into a problem and I can't seem to find a good solution to make it work. I have to make some dynamic routes into a Zend Framework project. I'll explain shortly what my problem is:

I need to have dynamic custom routes that "extend" the default route (module/controller/action/params). The project I'm working for has several partners and the routes have to work with those. To store the partners I've made a static class and it looks like this.

<?php
    class App_Partner
    {
        static public $partners = array(
            array(
                'name' => 'partner1',
                'picture' => 'partner1.jpg'
            ),
            array(
                'name' => 'partner2',
                'picture' => 'partner2.jpg'
            ),
            array(
                'name' => 'partner3',
                'picture' => 'partner3.jpg'
            )
        );
        static public function routePartners() {
            $partners = array();

            foreach(self::$partners as $partner) {
                array_push($partners, strtolower($partner['name']));
            }
            $regex = '(' . implode('|', $partners) . ')';

            return $regex;
        }
    }

So App_Partner::routePartners() return me a string like (partner1|partner2|partner3) which I use to create the right routes. My goal is to have the custom routes for each partner for every route I have set in the Bootstrap. So if I have a route add-product.html set I want it to work for each partner as partner1/add-product.html, partner2/add-product.html and partner3/add-product.html. Also, partner1/, partner2/, partner3 should route to default/index/index.

In fa开发者_如何学编程ct, I made this thing to work using routes like the one below.

<?php
$routeProposal = new Zend_Controller_Router_Route_Regex(
    App_Partner::routePartners() . '?/?proposals.html',
    array(
        'module' => 'default',
        'controller' => 'proposal',
        'action' => 'index',
        'page' => 1
    ),
    array( 1 => 'partner'),
    "%s/proposals.html"
);
$router->addRoute('proposal', $routeProposal);

The problem

The above route works fine if I use a partner in the request URI, but if I don't, I get double slashes like public//proposals.html because of the reverse route set in the route above to be "%s/proposals.html". I can't seem to find a way to avoid this reverse route because I build my urls using the url view helper and if the reverse route isn't set I get an exception stating this.

I also need the routes to work without a partner set, which will be the default way (add-product.html, proposals.html etc).


From your description, it seems like you're looking for a zend router chain, where your partner is an optional chain.

Here's a similar question, but using a hostname route : Zend Framework: get subdomain parameter from route. I adapted it to solve your problem, just put the following in your Bootstrap.php to initialize the routing :

protected function _initRoute()
{
    $this->bootstrap('FrontController');
    $router = $this->getResource('FrontController')->getRouter();

    // Default route
    $router->removeDefaultRoutes();
    $defaultRoute = new Zend_Controller_Router_Route(
                    ':controller/:action/*',
                    array(
                        'module' => 'default',
                        'controller' => 'index',
                        'action' => 'index',
                    )
    );
    $router->addRoute('default', $defaultRoute);

    $partnerRoute = new Zend_Controller_Router_Route(
        ':partner',
        array('partner' => 'none'),
        array('partner' => '^(partner1|partner2|partner3)$')
    );
    $router->addRoute('partner', $partnerRoute->chain($defaultRoute));
}

Change as you see fit. In your controllers you will only get a value for the partner parameter if it was actually specified AND valid (you will get a routing error if the partner doesn't exist)...


I use a similar process to detech lang, in my route (but with a ini file).

You can use a default value for you partners parameter to make the route working without partner, and add a ? to your regex.

But actually, I don't know how to avoid the double //...

Hope that helps.

EDIT: For your information, here is a simplified version of my route with language:

routes.lang.type = "Zend_Controller_Router_Route"
routes.lang.route = "lang/:language/*"
routes.lang.reqs.language = "^(en|fr|nl|de)?$"
routes.lang.defaults.language = none
routes.lang.defaults.module = default
routes.lang.defaults.controller = index
routes.lang.defaults.action = language
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜