Zend_Controller_Router_Exception: “xyz” is not spe

2019-01-20 00:34发布

问题:

I have a problem in my current Zend Framework application.

In my Bootstrap I register these routes:

protected function _initRouter()
{
    $this->bootstrap("FrontController");
    $frontController = $this->getResource("FrontController");

    $route = new Zend_Controller_Router_Route(
        ":module/:id",
        array(
            "controller" => "index",
            "action" => "index"
            ),
        array("id" => "\d+")
        );
    $frontController->getRouter()->addRoute('shortcutOne', $route);

    $route = new Zend_Controller_Router_Route(
        ":module/:controller/:id",
        array("action" => "index"),
        array("id" => "\d+")
        );
    $frontController->getRouter()->addRoute('shortcutTwo', $route);

    $route = new Zend_Controller_Router_Route(
        ":module/:controller/:action/:id",
        null,
        array("id" => "\d+", "action" => "\w+")
        );
    $frontController->getRouter()->addRoute('shortcutThree', $route);
}

Now later I added Zend_Navigation to my project. I have several modules, that register navigation elements in the module bootstrap:

<?php

class Contact_Bootstrap extends Zend_Application_Module_Bootstrap
{
    protected function _initNavigation()
    {
        $layout = $this->getApplication()->getResource("layout");
        $view = $layout->getView();

        $config = new Zend_Config_Xml(dirname(__FILE__)."/config/navigation.xml", "nav");

        $view->navigation()->addPage($config);
    }
}

When I open the app in my browser everything works fine. That means I can see the navigation and click on its links to view the specified page. But when I hit a page that uses the :module/:action/:id route, the Navigation Helper throws a Zend_Controller_Router_Route exception:

Fatal error: Zend_Controller_Router_Exception: id is not specified in C:\Entwicklung\kt\trunk\src\library\Zend\View\Helper\Navigation\HelperAbstract.php on line 519

Did anyone of you experience this error too? It would be great if you could help me or give me advise. Also if you need more information on my setup etc., just tell me.

Thank you!

回答1:

I found the solution myself.

This problem was caused due to a not-so-beneficial behavior of the Zend_Navigation elements. In their getHref() method they use the URL helper. This helper creates the URL the navigation entry has to link to, taking in the arguments specified for the navigation element (module, controller, action, etc.)

Now, the problem is that, if you have created a custom route in your bootstrap just as I did, for example

":module/:controller/:id"

You run into the problem that when this route is being used, the URL helper uses that route to generate the link for the navigation entry. However, I did not pass on an additional "id" parameter, so I got the exception.

So one solution is to pass an additional parameter for each Zend_Navigation_Page_Mvc instance "route" which is set to "default".

Another solution, which I didn't try yet, is to let the new custom route just re-map itself onto the default route, like:

":module/:controller/:action/id/$id"

But I don't know if you have the ability with Zend Framework to do that.



回答2:

$route = new Zend_Controller_Router_Route( 
    "info/:id", 
    array( 
        "controller" => "index", 
        "action" => "index" 
    ), 
    array("id" => "\d+") 
); 

changed to

$route = new Zend_Controller_Router_Route( 
    "info/:id", 
    array( 
        "controller" => "index", 
        "action" => "index",
        "id" => "default"
    )
); 

worked for me, but probably isn't the best way to go



回答3:

I have faced the same problem and here the solution that worked for me: I added route parameter to my all links in my navigation.xml file as below

    <?xml version="1.0" encoding="UTF-8"?>
    <navigation>
        <mainmenu>
        <home>
                <label>topmenu:homepage</label>
                ===> <route>default</route> <===
                <module>default</module>
                <controller>index</controller>
                <action>index</action>
        </home>
    </mainmenu>
</navigation>


回答4:

In this route ":module/:controller/:id" you need simply define default value for :id

Example:

<content type="Zend_Controller_Router_Route">
    <route>content/:engine</route>
    <defaults module="content" controller="engine" action="index" engine="" />
</content>

Sorry for my English :)

Regards.



回答5:

I've just encountered a problem similar to yours but have found a different workaround for it. I'll share it here just for the sake of information.

Just like you, my problem seemed to be that my navigation was built using the route last used. This meant that if one of my custom routes had been used, I'd get a stack of exceptions complaining about some custom parameters for this given route not being defined.

Most of my routes' custom parameters' value default to null in my route definition. I discovered if I changed the default value to '' instead, the exception would actually disappear. I couldn't really understand this so I began googling a bit and stumbled across your post which led me onto the right path - I think.

My navigational elements are stored in a database so I generate all my Zend_Navigation_Page elements upon request and pass the container to my view helpers (I do serialize my container object to make it cacheable, but that's not relevant right now). I didn't really find that changing the params' default value to '' seeemed like a "good" way of doing it, so hinted by your post I tried to change all my page elements, stored in my database, to use a route named 'default' unless they explicitly was meant to use a custom route and had the params defined for it. Explicitly defining my navigational points to use the default route seemed to do the trick also and to me it seems as a more clean workaround.

Thanks for the hint to what was causing this error - with the exception, I really had no clue about where to start :)



回答6:

I see here two solutions:

  1. You can set a default value for your route parameters in the _initRouter(), but it may be not what you want (eg. in this case this route may be used when you do not want)

  2. You can specify the route parameters in the navigation.xml (the params property). If you don't want to set them fixed, you will need to write PHP code for the generation of the navigation xml.