Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Working with prefixes and Zend_Controller_Router_Route

On an existing Zend Framework website with few controllers and no modules I need to add some prefixes to the default routes.

For example, I currently have :

/products
/products/id/1
/training
/commonpage

I want to add a product line level, without duplicating my controllers in x modules (I'll just request the right product line inside my controllers with _getParam ).

So my new paths will be :

/line1/products
/line1/products/id/1
/line2/training
/commonpage

What I tried so far is this route (located in my Bootstrap file) :

protected function _initRoutes()
{
    $router = Zend_Controller_Front::getInstance()->getRouter();
    $router->addRoute('productLineRoute', new Zend_Controller_Router_Route(
        ':line/:controller/:action',
        array('module' => 'default'),
        array('line' => '(' . implode('|', Zend_Registry::getInstance()->constants->lines) . ')')
    ));
}

But without any success (it gives me a 404). How can I build a single route that match all uri under those conditions :

  • The prefix of the uri match a value in my product lines array
  • The route is valid only if the controller requested is allowed to be accessed in a "product line way" - by an array containing the names of my controllers for example

UPDATE

Ok I managed to get really close of what I'm trying to do with this code :

protected function _initConstants()
{
    $registry = Zend_Registry::getInstance();
    $registry->constants = new Zend_Config( $this->getApplication()->getOption('constants') );
    $uri = ltrim($_SERVER['REQUEST_URI'], '/');
    $product_line = substr($uri, 0, strpos($uri, '/'));
    if(!empty($product_line) && in_array($product_line, Zend_Registry::getInstance()->constants->lines->toArray()) &&
       $product_line != Zend_Registry::getInstance()->constants->lines->get(0)) {
        $registry->product_line = $product_line;
    } elseif(!isset($registry->gamme)) {
        $registry->product_line = Zend_Registry::getInstance()->constants->lines->get(0);
    }
}

protected function _initRoutes()
{
    $router = Zend_Controller_Front::getInstance()->getRouter();
    $registry = Zend_Registry::getInstance();
    $router->addRoute('productLineRoute', new Zend_Controller_Router_Route(
        ':line/:controller/:action/*',
        array(
            'module' => 'default', 'action' => 'index',
            'line'  => (isset($registry->product_line)) ? $registry->product_line : Zend_Registry::getInstance()->constants->lines->get(0)
        ),
        array(
            'line'      => '(' . implode('|', Zend_Registry::getInstance()->constants->lines->toArray()) . ')',
            'controller' => '(' . implode('|', array('products', 'training')) . ')'
        )
    ));
}

With that I can access /line1/products but not /line1/commonpage, which is what I want - so the controller constraint is working great. As you can see I add the product line name in the Zend Registry, so it is saved when I use the URL View Helper in templates (that way I don't have to edit all my templates to add the product line parameter in my helper calls).

The problem I have now is about this helper : it seems that my controller constraint is just get ignored. When I do this in my template:

<a href="<?php echo $this->url(array('controller'=> 'commonpage', 'action'=>'index'),null, true) ; ?>">My link</a>

I end up with this :

<a href="/line1/commonpage">My link</a>

So the product line is added, despite of the fact that this is not allowed by the controller constraint of my route.

like image 909
vard Avatar asked May 05 '15 10:05

vard


1 Answers

Ok I found a solution : I changed the URL Helper to add the controller constraint inside it. If the controller doesn't match the "product lines controllers" array, it force assemble to use the default route (not perfect, but it works for me):

public function url(array $urlOptions = array(), $name = null, $reset = false, $encode = true, $default = false)
    {
        $router = Zend_Controller_Front::getInstance()->getRouter();
        if(isset($urlOptions['controller']) && !in_array($urlOptions['controller'], array('products', 'training'))) {
            $name = 'default';
        }
        return $router->assemble($urlOptions, $name, $reset, $encode);
    }
like image 147
vard Avatar answered Nov 08 '22 01:11

vard