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 :
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.
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With