I am using the default ErrorController
that Zend Tool generated for me. The very first thing my index.php
file does is to register an error handler that converts errors and warnings into exceptions:
function handleError($errno, $errstr, $errfile, $errline, array $errcontext) {
// error was suppressed with the @-operator
if (0 === error_reporting()) {
return false;
}
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler('handleError');
I also have this set up in index.php
:
$front = Zend_Controller_Front::getInstance();
$front->throwExceptions(false);
The problem is that it doesn't handle exceptions that come from the Bootstrap file. The exception fires, but the ErrorController
doesn't pick it up. Execution of the page simply halts and no views are rendered.
How can I route every exception and warning through the error controller (with the exception of syntax and fatal errors, of course)?
If an Exception occurs in the Bootstrap then it cannot be passed to the ErrorController
because your application has not been set up yet so it has no idea about the ErrorController
yet.
You'll have to use something else to handle it.
Having an application which is highly likely to throw an uncaught Exception in the Bootstrap is surely not a good thing. You should catch the Exceptions that occur in the Bootstrap and handle them accordingly.
But if you connect to the database JIT (Just In Time), there should be no problem. You can actually move the database connection after bootstrap using Front Controller plugins. The DB connection setup can be at _dispatchLoopStartup()
if you don't need it to setup other things (like routes, some pre-dispatch translations, etc).
//in bootstrap
$front->registerPlugin(new Awesome_Db_Plugin($zendConfigWithDbOptions));
// in plugin (options injected via constructor to private member
public function dispatchLoopStartup() {
$db = Zend_Db::factory($this->_options);
Zend_Registry::set('db', $db);
}
This way every exception thrown during the db connection will be fired after $front->dispatch();
this is from my index.php, may be it'll be useful:
//bootstrap, and run application
try {
require_once 'Zend/Application.php';
//create application and configure it.
$application = new Zend_Application(
getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production',
array('config' => array(APPLICATION_PATH . DS . 'configs' . DS . 'application.ini'))
);
//run application
$application->bootstrap()->run();
} catch (Exception $e) {
//fallback for uncatched exceptions
ob_clean();
//ensure error will be logged and firephp backend, if enabled, will send log messages
if(is_object($application)
&& $application->bootstrap('log')
&& Zend_Registry::isRegistered('Zend_Log')
) {
Zend_Registry::get('Zend_Log')
->log($e,Zend_Log::CRIT);
}
$wildfire = Zend_Wildfire_Channel_HttpHeaders::getInstance();
if(!($response = Zend_Controller_Front::getInstance()->getResponse())) {
$response = new Zend_Controller_Response_Http();
$wildfire->setRequest(new Zend_Controller_Request_Http());
$wildfire->setResponse($response);
}
if($response->canSendHeaders()) {
$response->clearHeaders();
$response->setHttpResponseCode(500);
$wildfire->flush();
$response->sendResponse();
}
//put static html for error page here
echo 'Startup error occured. Try again later';
}
note: Zend_Registry::isRegistered('Zend_Log')
Zend_Log instance registered with registry in my extended application resource