I am working on a project with a growing API. Our responses are all JSON, and we started to handle errors in the API controllers instead of the ErrorController.
To make it more easy I altered the ErrorController to also response in JSON and use the corresponding HTTP status and created a HttpStatusCode class for use within my Zend Framework Project.
<?php
/**
* HttpStatusCodes
* */
class API_Model_HttpStatusCode
{
// 1xx Informational
const INFORMATIONAL_CONTINUE = 100;
const INFORMATIONAL_SWITCHING_PROTOCOLS = 101;
const INFORMATIONAL_PROCESSING = 102;
const INFORMATIONAL_CHECKPOINT = 103;
const INFORMATIONAL_REQUEST_URI_TOO_LONG = 122;
// 2xx Success
const SUCCESS_OK = 200;
const SUCCESS_CREATED = 201;
const SUCCESS_ACCEPTED = 202;
const SUCCESS_NON_AUTHORITATIVE_INFORMATION = 203;
const SUCCESS_NO_CONTENT = 204;
const SUCCESS_RESET_CONTENT = 205;
const SUCCESS_PARTIAL_CONTENT = 206;
const SUCCESS_MULTI_STATUS = 207;
const SUCCESS_IM_USED = 226;
// 3xx Redirection
const REDIRECTION_MULTIPLE_CHOICES = 300;
const REDIRECTION_MOVED_PERMANETLY = 301;
const REDIRECTION_FOUND = 302;
const REDIRECTION_SEE_OTHER = 303;
const REDIRECTION_NOT_MODIFIED = 304;
const REDIRECTION_USE_PROXY = 305;
const REDIRECTION_SWITCH_PROXY = 306;
const REDIRECTION_TEMPORARY_REDIRECT = 307;
const REDIRECTION_RESUME_INCOMPLETE = 308;
// 4xx Client Error
const CLIENT_ERROR_BAD_REQUEST = 400;
const CLIENT_ERROR_UNAUTHORIZED = 401;
const CLIENT_ERROR_PAYMENT_REQUIRED = 402;
const CLIENT_ERROR_FORBIDDEN = 403;
const CLIENT_ERROR_NOT_FOUND = 404;
const CLIENT_ERROR_METHOD_NOT_ALLOWED = 405;
const CLIENT_ERROR_NOT_ACCEPTABLE = 406;
const CLIENT_ERROR_PROXY_AUTHENTICATION_REQUIRED = 407;
const CLIENT_ERROR_REQUEST_TIMEOUT = 408;
const CLIENT_ERROR_CONFLICT = 409;
const CLIENT_ERROR_GONE = 410;
const CLIENT_ERROR_LENGHT_REQUIRED = 411;
const CLIENT_ERROR_PRECONDITION_FAILED = 412;
const CLIENT_ERROR_REQUEST_ENTITY_TOO_LARGE = 413;
const CLIENT_ERROR_REQUEST_URI_TOO_LONG = 414;
const CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE = 415;
const CLIENT_ERROR_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
const CLIENT_ERROR_EXPECTATION_FAILED = 417;
const CLIENT_ERROR_I_AM_A_TEAPOT = 418;
const CLIENT_ERROR_UNPROCESSABLE_ENTITY = 422;
const CLIENT_ERROR_LOCKED = 423;
const CLIENT_ERROR_FAILED_DEPENDENCY = 424;
const CLIENT_ERROR_UNORDERED_COLLECTION = 425;
const CLIENT_ERROR_UPGRADE_REQUIRED = 426;
const CLIENT_ERROR_NO_RESPONSE = 444;
const CLIENT_ERROR_RETRY_WITH = 449;
const CLIENT_ERROR_BLOCKED_BY_WINDOWS_PARENTAL_CONTROLS = 450;
const CLIENT_ERROR_CLIENT_CLOSED_REQUEST = 499;
// 5xx Server Error
const SERVER_ERROR_INTERNAL_SERVER_ERROR = 500;
const SERVER_ERROR_NOT_IMPLEMENTED = 501;
const SERVER_ERROR_BAD_GATEWAY = 502;
const SERVER_ERROR_SERVICE_UNAVAILABLE = 503;
const SERVER_ERROR_GATEWAY_TIMEOUT = 504;
const SERVER_ERROR_HTTP_VERSION_NOT_SUPPORTED = 505;
const SERVER_ERROR_VARIANT_ALSO_NEGOTIATES = 506;
const SERVER_ERROR_INSUFFICIENT_STORAGE = 507;
const SERVER_ERROR_BANDWITH_LIMIT_EXCEEDED = 509;
const SERVER_ERROR_NOT_EXTENDED = 510;
const SERVER_ERROR_NETWORK_READ_TIMEOUT_ERROR = 598;
const SERVER_ERROR_NETWORK_CONNECT_TIMEOUT_ERROR = 599;
}
<?php
/**
* Basic error controller
*/
class ErrorController extends Zend_Controller_Action
{
/**
* Catches the error. Displays a error page..
*
* @return void
*/
public function errorAction ()
{
/** @var Zend_Exception */
$errors = $this->_getParam('error_handler');
/* @var $error Zend_Exception */
$error = $errors->exception;
switch ($error->getCode()) {
case API_Model_HttpStatusCode::INFORMATIONAL_CONTINUE:
case API_Model_HttpStatusCode::INFORMATIONAL_SWITCHING_PROTOCOLS:
case API_Model_HttpStatusCode::INFORMATIONAL_PROCESSING:
case API_Model_HttpStatusCode::INFORMATIONAL_CHECKPOINT:
case API_Model_HttpStatusCode::INFORMATIONAL_REQUEST_URI_TOO_LONG:
case API_Model_HttpStatusCode::SUCCESS_OK:
case API_Model_HttpStatusCode::SUCCESS_CREATED:
case API_Model_HttpStatusCode::SUCCESS_ACCEPTED:
case API_Model_HttpStatusCode::SUCCESS_NON_AUTHORITATIVE_INFORMATION:
case API_Model_HttpStatusCode::SUCCESS_NO_CONTENT:
case API_Model_HttpStatusCode::SUCCESS_RESET_CONTENT:
case API_Model_HttpStatusCode::SUCCESS_PARTIAL_CONTENT:
case API_Model_HttpStatusCode::SUCCESS_MULTI_STATUS:
case API_Model_HttpStatusCode::SUCCESS_IM_USED:
case API_Model_HttpStatusCode::REDIRECTION_MULTIPLE_CHOICES:
case API_Model_HttpStatusCode::REDIRECTION_MOVED_PERMANETLY:
case API_Model_HttpStatusCode::REDIRECTION_FOUND:
case API_Model_HttpStatusCode::REDIRECTION_SEE_OTHER:
case API_Model_HttpStatusCode::REDIRECTION_NOT_MODIFIED:
case API_Model_HttpStatusCode::REDIRECTION_USE_PROXY:
case API_Model_HttpStatusCode::REDIRECTION_SWITCH_PROXY:
case API_Model_HttpStatusCode::REDIRECTION_TEMPORARY_REDIRECT:
case API_Model_HttpStatusCode::REDIRECTION_RESUME_INCOMPLETE:
case API_Model_HttpStatusCode::CLIENT_ERROR_BAD_REQUEST:
case API_Model_HttpStatusCode::CLIENT_ERROR_UNAUTHORIZED:
case API_Model_HttpStatusCode::CLIENT_ERROR_PAYMENT_REQUIRED:
case API_Model_HttpStatusCode::CLIENT_ERROR_FORBIDDEN:
case API_Model_HttpStatusCode::CLIENT_ERROR_NOT_FOUND:
case API_Model_HttpStatusCode::CLIENT_ERROR_METHOD_NOT_ALLOWED:
case API_Model_HttpStatusCode::CLIENT_ERROR_NOT_ACCEPTABLE:
case API_Model_HttpStatusCode::CLIENT_ERROR_PROXY_AUTHENTICATION_REQUIRED:
case API_Model_HttpStatusCode::CLIENT_ERROR_REQUEST_TIMEOUT:
case API_Model_HttpStatusCode::CLIENT_ERROR_CONFLICT:
case API_Model_HttpStatusCode::CLIENT_ERROR_GONE:
case API_Model_HttpStatusCode::CLIENT_ERROR_LENGHT_REQUIRED:
case API_Model_HttpStatusCode::CLIENT_ERROR_PRECONDITION_FAILED:
case API_Model_HttpStatusCode::CLIENT_ERROR_REQUEST_ENTITY_TOO_LARGE:
case API_Model_HttpStatusCode::CLIENT_ERROR_REQUEST_URI_TOO_LONG:
case API_Model_HttpStatusCode::CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE:
case API_Model_HttpStatusCode::CLIENT_ERROR_REQUESTED_RANGE_NOT_SATISFIABLE:
case API_Model_HttpStatusCode::CLIENT_ERROR_EXPECTATION_FAILED:
case API_Model_HttpStatusCode::CLIENT_ERROR_I_AM_A_TEAPOT:
case API_Model_HttpStatusCode::CLIENT_ERROR_UNPROCESSABLE_ENTITY:
case API_Model_HttpStatusCode::CLIENT_ERROR_LOCKED:
case API_Model_HttpStatusCode::CLIENT_ERROR_FAILED_DEPENDENCY:
case API_Model_HttpStatusCode::CLIENT_ERROR_UNORDERED_COLLECTION:
case API_Model_HttpStatusCode::CLIENT_ERROR_UPGRADE_REQUIRED:
case API_Model_HttpStatusCode::CLIENT_ERROR_NO_RESPONSE:
case API_Model_HttpStatusCode::CLIENT_ERROR_RETRY_WITH:
case API_Model_HttpStatusCode::CLIENT_ERROR_BLOCKED_BY_WINDOWS_PARENTAL_CONTROLS:
case API_Model_HttpStatusCode::CLIENT_ERROR_CLIENT_CLOSED_REQUEST:
case API_Model_HttpStatusCode::SERVER_ERROR_INTERNAL_SERVER_ERROR:
case API_Model_HttpStatusCode::SERVER_ERROR_NOT_IMPLEMENTED:
case API_Model_HttpStatusCode::SERVER_ERROR_BAD_GATEWAY:
case API_Model_HttpStatusCode::SERVER_ERROR_SERVICE_UNAVAILABLE:
case API_Model_HttpStatusCode::SERVER_ERROR_GATEWAY_TIMEOUT:
case API_Model_HttpStatusCode::SERVER_ERROR_HTTP_VERSION_NOT_SUPPORTED:
case API_Model_HttpStatusCode::SERVER_ERROR_VARIANT_ALSO_NEGOTIATES:
case API_Model_HttpStatusCode::SERVER_ERROR_INSUFFICIENT_STORAGE:
case API_Model_HttpStatusCode::SERVER_ERROR_BANDWITH_LIMIT_EXCEEDED:
case API_Model_HttpStatusCode::SERVER_ERROR_NOT_EXTENDED:
case API_Model_HttpStatusCode::SERVER_ERROR_NETWORK_READ_TIMEOUT_ERROR:
case API_Model_HttpStatusCode::SERVER_ERROR_NETWORK_CONNECT_TIMEOUT_ERROR:
$this->getResponse()->setHttpResponseCode($error->getCode());
$priority = Zend_Log::NOTICE;
$this->_helper->json->sendJson( array('Error' => $error->getMessage()));
break;
default:
switch ($error->getCode()) {
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
// 404 error -- controller or action not found
$this->getResponse()->setHttpResponseCode(404);
$priority = Zend_Log::NOTICE;
$this->_helper->json->sendJson(
array('Error' => $error->getMessage()));
break;
default:
// application error
$this->getResponse()->setHttpResponseCode(500);
$priority = Zend_Log::CRIT;
$this->_helper->json->sendJson(array('Error' => $error->getMessage()));
break;
}
}
}
}
If you have an exception somewhere just throw a new one, and the ErrorController will handle the rest
throw new Zend_Exception ( "Error connection to database", API_Model_HttpStatusCode::SERVER_ERROR_SERVICE_UNAVAILABLE );
Make sure to set in your application.ini
resources.frontController.throwExceptions = 0
Tags: ErrorController, php, zend framework
updated the errorController to fix a small bug..