问题
As mentioned in the Zend Framework manual, I created a base controller.
Subclassing the Action Controller
By design, Zend_Controller_Action must be subclassed in order to create an action controller. At the minimum, you will need to define action methods that the controller may call.
Besides creating useful functionality for your web applications, you may also find that you're repeating much of the same setup or utility methods in your various controllers; if so, creating a common base controller class that extends Zend_Controller_Action could solve such redundancy.
But it turns out, that Exceptions are not being called properly from the base... To replicate this, create a file:
/path/to/workspace/library/Joe/Controller.php
Then:
class Joe_Controller extends Zend_Controller_Action
{
public function init()
{
Throw new Zend_Exception('test', 500);
parent::init();
}
}
Then in your controller directory, IndexController.php extends off the base:
class IndexController extends Joe_Controller
{
You will find that the exception is uncaught.
If however, you don't extend off the base controller, then throw an exception in init or preDispatch, it will be caught and forwarded to the ErrorController.
Anyone have an idea on getting the exceptions caught from the Base Controller?
Thanks.
UPDATING TO TACKLE THIS ANOTHER WAY
After looking at the various articles and official documentation on how to structure the directories, I went with putting the base controller in library/Joe/...but maybe that's part of the problem...there's no guidance in the manual on how to name and place the base controller. What do the experts with a base controller do?
Another Update
Looking at my code some more, and reading on the net, seems like people suggested in should be:
abstract class Joe_Controller_Action extends Zend_Controller_Action.
Except changing it did not solve the problem...
Now considering that there are articles suggesting to use Base Controllers including the manual, would this be considered a bug in Zend Framework?
To replicate, just throw a Zend_Exception of any kind in the base init or preDispatch. Imagine you poll the database in there, (which is what I'm doing)...and the database is down. No error controller. That's not a good situation unless I'm doing something incorrectly.
My suspicion is that this is a new bug... I don't recall this problem before Zend_Application and I've been using a base controller since ZF 1.5.
回答1:
Two thoughts off the top of my head:
Controller names in the default module are usually named like
SomethingController
. Your nameJoe_Controller
suggests the moduleJoe
and an empty controller name.In routing/dispatch, doesn't it look for a matching action before dispatch to the controller? Since the samples have no actions, might you be triggering ControllerNotFound exception?
Just throwin' out some ideas.
回答2:
in Zend philosophy, they provide the init() method to avoid the hassle of
public class Module_TotoController extends Zend_Action_Controller {
public function __construct(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, array $invokeArgs = array())
parent::__construct($request, $response, invokeArgs);
// some init code here
}
}
just use :
public class Module_TotoController extends Zend_Action_Controller {
public function init ()
// some init code here
}
}
Now, If you look at the Zend_Controller_Action
class source, you will notice that the following methods are empty:
init()
preDispatch ()
postDispatch ()
This means, it is useless to call parent::
in your specific controller
public class Module_TotoController extends Zend_Action_Controller {
public function init ()
parent::init(); // useless ;-) but you can go for it
// some init code here
}
}
Now, if you want to put an intermediate class between Module_TotoController
and Zend_Action_Controller
, you expose yourself to a big hassle as:
- Some controllers won't extend your "base" controller (e.g your ErrorController in your question)
- so it is not a really a base of your application, is it ?
- If you put some logic in your init() of that "base",
- you must call the
parent::
in yourinit()
, - all the developers in the project need to be aware of that
- you must call the
- You will ever add another little features to your "Base" controller
- This will result to a big bloated file
- Loading/Initializing plenty of stuff you might not really need in that lambda controller
- Do you need you database on every page ?
- No: doesn't a
$this->_helper->connect();
look nice instead ? - Yes: use a controller plugin
- No: doesn't a
- Do you need you database on every page ?
- This "Base" controller won't fit your other projects needs, so that class won't be reusable
- Action helpers will
- Controller Plugins will
Hope it makes sense
回答3:
Don't go for a base or whatever controller
As documentation says :
By design, Zend_Controller_Action must be subclassed in order to create an action controller.
Agreed, this is misleading What they meant is
class Module_TotoController extends Zend_Controller_Action {}
class Module_TotoController extends Joe_Controller
is plain wrong (sorry no offence)
as you said your ErrorController
can't extend your intermediate Joe_Controller
class
because your exception will be thrown again in the instantiation of the ErrorController
class (as excepted !!!)
The uncaught Exception
error is the result of a protection to avoid loops (dig Zend\Controller\Plugin\ErrorHanlder.php
line 200-ish)
If you require something to be done for every action, use a Zend_Controller_Plugin
and register it with the frontController
来源:https://stackoverflow.com/questions/3774768/how-to-handle-zend-exceptions-in-predispatch-or-init-of-an-action-when-using-a