History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: ZF-3465
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Priority: Critical Critical
Assignee: Matthew Weier O'Phinney
Reporter: Marek
Votes: 0
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
Google issue summary
Zend Framework

dispatcher - error when removing default routes

Created: 17/Jun/08 12:18 AM   Updated: 26/May/09 03:37 PM
Component/s: Zend_Controller
Affects Version/s: 1.5.2
Fix Version/s: None

Time Tracking:
Not Specified

Tags:
Participants: Lorenzo Alberton, Marek and Matthew Weier O'Phinney


 Description  « Hide
I think there is a bug in Zend/Controller/Dispatcher/Standard.php line 247.
Now: if (!$this->getParam('useDefaultControllerAlways') && !empty($controller)) {
Should be: if (!$this->getParam('useDefaultControllerAlways') && empty($controller)) {

Why? Even if we remove default routes ($router->removeDefaultRoutes(); ) we are always being redirected to index/index controller/action. So:
$front->throwExceptions(true) + $router->removeDefaultRoutes() = index/index
$front->throwExceptions(true) + #$router->removeDefaultRoutes() = exception

According to docs (http://framework.zend.com/manual/en/zend.controller.exceptions.html#zend.controller.exceptions.handling)
$dispatcher->setParam('useDefaultControllerAlways', true);
should switch between exception and default controller but now it isn't.

Of course, I could be wrong

edit: yes, it's definitely a bug. I've chcecked all possible combinations with routes / errorplugin / exception and now it's fine.



 All   Comments   Work Log   Change History   FishEye   Crucible      Sort Order: Ascending order - Click to sort in descending order
Matthew Weier O'Phinney - 24/Nov/08 11:36 AM
Actually, the current behavior is correct. When the useDefaultControllerAlways is set to true, then isDispatchable() will always return true – because it will resolve the invalid or empty controller to the default controller. I've tested extensively, and it works exactly as expected.

The one issue I've had with this is if I set the parameter after dispatch() has already been called on the front controller – i.e., from a plugin. In such a case, by the time that routeStartup() has hit, pushing the parameters into the front controller will have no effect on the router or dispatcher. If this is what you are doing, you may need to push that setParam() into your bootstrap or index.php prior to calling dispatch().


Marek - 24/Nov/08 10:44 PM
Sorry, I can't agree with You. My bootstrap.php:
$frontController = Zend_Controller_Front::getInstance();
$frontController->throwExceptions(true);
$frontController->setRouter($router);
$frontController->setParam('noViewRenderer', true);
$frontController->setParam('useDefaultControllerAlways', true);
$frontController->setControllerDirectory('../application/modules/default/controllers');
$frontController->registerPlugin(...some plugins here...);

$frontController->returnResponse(true);
$response = $frontController->dispatch();

/My own class for handling headers./
$response->sendResponse();

And let's try my code, set $frontController->setParam('useDefaultControllerAlways', false); and go to http://domain/non/existent > Invalid controller specified. Now $frontController>throwExceptions(false); -> Action "error" does not exist and was not trapped in __call(). W can read http://framework.zend.com/manual/en/zend.controller.exceptions.html "By default, the error handler plugin is registered and active...By passing a boolean true value to this method, you can tell the front controller that instead of aggregating exceptions in the response object or using the error handler plugin, you'd rather handle them yourself.". So as You can see everything is working as it should.

Now use default ZF code. $frontController->setParam('useDefaultControllerAlways', false); and go to http://domain/non/existent > index/index was loaded. Why? $frontController>throwExceptions(false); -> index/index . Nothing is working. You can also search google - there are several sites where people complain of such strange behavior.


Matthew Weier O'Phinney - 25/Nov/08 05:11 AM
I have done exactly what you suggest: I used a stock ZF install, with only an IndexController and ErrorController defined, and set the useDefaultControllerAlways param to false. In such a case, passing an invalid controller correctly goes to the ErrorController. Toggling the flag to true, I correctly go to the IndexController. This is exactly the behavior that is expected.

That said, I think I know where the confusion lies: when an action is also provided via the URL. Let's look at the flow:

  • invalid controller detected
  • controller rewritten to IndexController
  • action called on IndexController
  • IndexController does not find action method, and invokes __call()
  • __call() recognizes that an undefined action was called, and throws an exception
  • the ErrorHandler plugin detects the exception and invokes the ErrorController

So, the useDefaultControllerAlways flag is doing exactly as it should. The problem is that there is an expectation that the action controller will fall back to a default action as well. And that's the real issue here.

I'm re-opening the issue and noting that when the default controller is selected in such a case that the default action as defined in the dispatcher should also be utilized.


Marek - 25/Nov/08 06:39 AM
It was some time ago when I reported this bug so I forgot real problem here was $router->removeDefaultRoutes(). What You said is valid for general, default routes. Could You please explain to me what exactly should happen if we changed ZF default routing?

Matthew Weier O'Phinney - 25/Nov/08 06:55 AM
Resolved in r12822 in trunk and r12823 in 1.7 release branch

Lorenzo Alberton - 17/Mar/09 04:25 AM
I can confirm this. Removing the default routes, the error controller is never called. Changing "!empty($controller)" to "empty($controller)", as suggested by the bug reporter, fixed the issue for me too.

Lorenzo Alberton - 26/May/09 03:37 PM
This bug is marked as resolved, but I can still reproduce it in the latest release (1.8.1). As reported by Marek, the problem happens when calling $router->removeDefaultRoutes(), and can be fixed by removing the "!" sign from within the "!empty($controller)" check.