I'm currently working on a project based on Zend 1.11 where I'm required to catch database related exceptions and display a notification should one occur. Needless to say I'm completely new to Zend Framework...
Judging by what I see in the default action defined within the ErrorController, I don't have a clue on how to achieve this:
class ErrorController extends Zend_Controller_Action
{
private $logPriority_;
public function errorAction()
{
$errors = $this->_getParam('error_handler');
if (!$errors || !$errors instanceof ArrayObject)
$this->_forward('notfound','error');
switch ($errors->type) {
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->_forward('notfound','error');
break;
default:
// application error
break;
}
$this->getResponse()->setHttpResponseCode(500);
$this->view->message = '500 Internal Server Error';
$this->logErrors(Zend_Log::CRIT);
}
// ...
Where and how should I approach this issue?
You can check if Zend_Db_Exception is thrown:
if($errors->exception and $errors->exception instanceof Zend_Db_Exception) {
// do something
}
Related
I am asking this question because I did not get reply after adding my comment in this question
laravel routing and 404 error
In the above answer, we can see below code to be used in filters.php
App::missing(function($exception)
{
return Response::view('errors.missing', array(), 404);
});
But, I think we don't have filters.php in latest version. Can somebody suggest better way to handle 404 error?
You don't need to do that anymore. Don't include that. What you do is put a view file (your 404 error view) called 404.blade.php in your resources/views/errors folder and Laravel will handle 404 errors for you.
take a look
http://www.jeffmould.com/2016/05/25/laravel-5-error-handling/
I just change this line App/Exceptions/Handler.php file.
public function render($request, Exception $e)
{
// the below code is for Whoops support. Since Whoops can open some security holes we want to only have it
// enabled in the debug environment. We also don't want Whoops to handle 404 and Validation related exceptions.
if (config('app.debug') && !($e instanceof ValidationException) && !($e instanceof HttpResponseException))
{
/******************here I changed**********************/
# return $this->renderExceptionWithWhoops($e);
return response()->view('errors.404', [], 404);
}
// this line allows you to redirect to a route or even back to the current page if there is a CSRF Token Mismatch
if($e instanceof TokenMismatchException){
return redirect()->route('index');
}
// let's add some support if a Model is not found
// for example, if you were to run a query for User #10000 and that user didn't exist we can return a 404 error
if ($e instanceof ModelNotFoundException) {
return response()->view('errors.404', [], 404);
}
// Let's return a default error page instead of the ugly Laravel error page when we have fatal exceptions
if($e instanceof \Symfony\Component\Debug\Exception\FatalErrorException) {
return \Response::view('errors.500',array(),500);
}
// finally we are back to the original default error handling provided by Laravel
if($this->isHttpException($e))
{
switch ($e->getStatusCode()) {
// not found
case 404:
return \Response::view('errors.404',array(),404);
break;
// internal error
case 500:
return \Response::view('errors.500',array(),500);
break;
default:
return $this->renderHttpException($e);
break;
}
}
else
{
return parent::render($request, $e);
}
/******************here I changed**********************/
#return parent::render($request, $e);
}
if (config('app.debug') && !($e instanceof ValidationException) && !($e instanceof HttpResponseException))
{
My ZF app is throwing an exception instead of returning a 404 for urls which are really 404s. E.g. testlotto.ie/rrr should be a 404, yet I get the following:
Fatal error: Uncaught exception 'Zend_Controller_Dispatcher_Exception' with message 'Invalid controller specified (rrr)' in /mnt/pc/sites/git-lotto/lotto/irish-lotto/library/Zend/Controller/Dispatcher/Standard.php:
I have tried the suggestions on Fatal error: Uncaught exception 'Zend_Controller_Dispatcher_Exception' while creating object of model class and Uncaught exception 'Zend_Controller_Dispatcher_Exception' (as well as many others), and nothing is working.
I do have my ErrorController controller in the ../application/controllers dir, which is what is returned when I die() out getControllerDirectory() from Controller/Dispatcher/Standard.php - so no problem of controller not being found.
My ErrorController is as follows (not that it matters as it is not getting called):
<?php
class ErrorController extends Zend_Controller_Action
{
public function errorAction()
{
$errors = $this->_getParam('error_handler');
switch ($errors->type) {
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);
$this->getResponse()->setRawHeader('HTTP/1.1 404 Not Found');
$content =<<<EOH
<h1>Unlucky!</h1>
<p>The url you entered is not a valid one - please check what you typed, the mistake is most likely there.</p>
EOH;
break;
default:
// application error
$content =<<<EOH
<h1>Error!</h1>
<p>An unexpected error occurred. Please try again later.</p>
EOH;
break;
}
// Clear previous content
$this->getResponse()->clearBody();
$this->view->content = $content;
}
}
The start of the despatch method is:
public function dispatch(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response)
{
$this->setResponse($response);
/**
* Get controller class
*/
if (!$this->isDispatchable($request)) {
$controller = $request->getControllerName();
//die($controller);
//$this->setParam('useDefaultControllerAlways',true);
//ErrorController::errorAction();
if (!$this->getParam('useDefaultControllerAlways') && !empty($controller)) {
require_once 'Zend/Controller/Dispatcher/Exception.php';
throw new Zend_Controller_Dispatcher_Exception('Invalid controller specified (' . $request->getControllerName() . ')');
}
$className = $this->getDefaultControllerClass($request);
As you can see, I tried as suggested setting setParam('useDefaultControllerAlways',true);, but all this achieves is the homepage of the website is rendered (default controller of course) with a 200 response code - I need a 404.
Also, $controller dies out as the "rrr" in this example.
My question is what do I need to do to get 404's returned? This used to work on my site - I just swapped servers and now it is not working.
The only solution I could find to this which worked (i.e. the site now correctly returns a 404 for urls which do not exist), was taken from http://www.christopherhogan.com/2012/06/13/zend-framework-404-page/
Specifically, adding the below to my bootstrap file does the trick:
try {
$frontController->dispatch(); //instead of just $frontController->dispatch();
} catch (Zend_Exception $e) {
// this is where the 404 goes
header( 'HTTP/1.0 404 Not Found' );
echo "<div style='float:center; width:1000px; margin:0 auto;'><img src='http://www.foundco.com/images/404.jpg' alt='Everything is gonna be fine, please do not panic!' /></div>";
}
However, it's not perfect, as my ErrorController does not get called into action. If anyone could suggest how to trigger my ErrorController from the bootstrap file, would be much appreciated.
i am searching for the code or script that is helpfull to insert all errors into mysql database.i do not know about it ,even not a little bit.
give me any idea about it.
how can i do this means insert all erros in database and the display them in my php page.
PHP lets you specify you own error handler - set_error_handler().
function error_handler($errno, $errstr, $errfile, $errline) {
global $db; //naughty use of global. You could re-create your database connection here instead.
switch ($errno) {
case E_NOTICE:
case E_USER_NOTICE:
$error = 'Notice';
break;
case E_WARNING:
case E_USER_WARNING:
$error = 'Warning';
break;
case E_ERROR:
case E_USER_ERROR:
$error = 'Fatal Error';
break;
default:
$error = 'Unknown';
break;
}
$db->query('INSERT INTO ...'); // create error log here
return true;
}
// Error Handler
set_error_handler('error_handler');
The parameters used in my custom function above have the same names as the manual:
$errno The first parameter, errno, contains the level of the error
raised, as an integer.
$errstr The second parameter, errstr, contains
the error message, as a string.
$errfile The third parameter is
optional, errfile, which contains the filename that the error was
raised in, as a string.
$errline The fourth parameter is optional,
errline, which contains the line number the error was raised at, as an
integer.
Using these parameters you should be able to determine what the error was, what file it was in, and what line it occured on.
i would use something like this to log custom error, but you can modify it around to store all encountered errors.
class Logger extends PDO{
private $_message;
public function __construct(){
parent::__construct("mysql:host={$host};dbname={$dbname};charset=utf8", $username, $password);//make sure these matches your database configs
return null;
}
public function setMessage($message){
$this->_message = $message;
return $this;
}
public function saveMessage(){
if (!isset($this->_message)){
die('Error Message has not been set');
}
$sql = 'INSERT INTO erros_table error_message,date_created';
$sql.= 'VALUES (:error_message,:date_created)';
$query = $this->prepare($sql);
$query->execute([':error_message' => $this->_message,':date_created' => date('y-m-d')]);
return null;
}
}
//now you will do something like this
//you can use this custom class anywhere
try{
//execute any code here
//and make sure to throw an error upon any code fail
//its up to you to throw exceptions on your custom code, but i advice you so
}catch(Exception $e){
$logger = new Logger();
$logger->setMessage($e->getMessage())->saveMessage();
}
You're question it's too generic. The main problem here is how to track errors and it's not clear if you want to track client side errors (javascript), server side errors (PHP) or transactions errors (MySQL).
In case you want to track all of these, you can develop you're own error handlers.
For example, for javascript I use this snippet of code:
window.jsErrors = [];
window.onerror = function(errorMessage, url, lineNumber) {
err = { "host" : window.location.host, "url" : url,
"error": errorMessage, "line" : lineNumber,
"user": "John" };
window.jsErrors[window.jsErrors.length] = err;
notify(err);
}
The notify funcion makes an ajax request.
For PHP, take a look at this.
For Java, take a look at Log4J DB appender
You should have to do like this for error hanling in mysql.
function throw_ex($er){
throw new Exception($er);
}
try {
$q = mysql_query("Insert into test (col1,col2,col3) VALUES ('blah','blah','blah')") or throw_ex(mysql_error());
}
catch(exception $e) {
echo "ex: ".$e;
}
Any tips on how to handle business logic errors? I do not mean Exceptions.
For example, lest assume that i have a class:
<?php
class Reactor () { // business class
public function shutdown() {
if($date > '2 pm') {
// show error message to user
echo 'you can't shutdown before 2 pm.';
} else {
// error while trying to shutdown
throw new Exception('Oh my God, it is gonna blow!!');
}
}
}
?>
The real question is how to pass the error message to my views?
Exceptions are good for exceptional cases. I'm very close to add ErroMessage and ErrorCode attributes to the base business class and check it every time i call a business class method.
You're actually on the right track here. You can handle the exceptions in your ErrorController - a convention modeled in Zend, but in many other frameworks too. You can create your own if you're rolling it DIY.
This thread has a more Zend-centric method of handling, but you can use the ErrorController to actually render your view. Handle the input of the $e exception class and get the message from that.
Throwing exceptions from model/view/controller in a Zend Framework application
If you're deep in the DIY route, you can display it gracefully if you wrap your larger blocks in try/catch and test all instances of the exception class. For instance:
class Reactor () { // business class
public function shutdown() {
if($date > '2 pm') {
// show error message to user
echo "you can't shutdown before 2 pm.";
} else {
// error while trying to shutdown
throw new Exception('Oh my God, it is gonna blow!!');
}
}
}
//later, in the controller
$reactor = new Reactor();
try{
$reactor->shutdown('1pm');
} catch(Your_Custom_Exception $e){
//pass to view
$this->view($e->getMessage());
} catch(Exception $e){
// woops, serious error. do something useful
}
Exceptions are exactly what you need in this case. State validation (this is what you're doing) shall lead either to silence or an exception. You shall handle Model-thrown exceptions in your Controller, convert them to messages and pass them to View.
I think you should have something like this.
Use attributes to store data and error message. And i think it is illogical to generate error for if and else too
class Reactor{
public $date;
public $error;
public $errorstatus = false;
//Use property to store data and errors
public function shutdown() {
if($date > 2) {
$this->errorstatus = true;
$this->error['date'] = "You cannot shutdown before 2 pm";
} else
return true;
}
}
$reactor = new Reactor();
$reactor->data = 3;
$reactor->shutdown();
if($reactor->errorstatus){
echo $reactor->error['date'];
}
else{
echo "Its already two you can shutdown";
}
echo "<br/>";
$reactor->data = 1;
$reactor->shutdown();
if($reactor->errorstatus){
echo $reactor->error['date'];
}
else{
echo "Its already two you can shutdown";
}
[UPDATE]
public function shutdown() {
if($date > 2) {
$this->errorstatus = true;
$this->error['date'] = "You cannot shutdown before 2 pm";
} else
if($this->poweroff)
return true;
else
throw new Exception("ERROR WHILE SHUTTING DOWN"):
}
private function poweroff()
{
//if power off then return true
//else return false
}
Currently I am using a basic error controller which looks like this:
class ErrorController extends My_MyController
{
public function errorAction()
{
$errors = $this->_getParam('error_handler');
switch ($errors->type) {
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()
->setRawHeader('HTTP/1.1 404 Not Found');
$this->view->headTitle('HTTP/1.1 404 Not Found');
$this->view->message = 'HTTP/1.1 404 Not Found';
break;
default:
// application error; display error page, but don't change
// status code
// Log the exception:
$exception = $errors->exception;
$log = new Zend_Log(
new Zend_Log_Writer_Stream(
BASE_PATH . '/logs/applicationException.log'
)
);
$log->debug($exception->getMessage() . "\n" .
$exception->getTraceAsString());
$this->view->headTitle('HTTP/1.1 404 Not Found');
$this->view->message = 'Application error';
break;
}
$this->view->exception = $errors->exception;
}
}
This, however, only catches and logs application exceptions. It won't log any warnings, notices and fatal errors.
I would like to log those as well. Is there a recommended way to do it in ErrorController? Or should it be done outside of the ErrorController in index.php (since Zend Framework ErrorHandler will only handle no route, missing application/action exceptions and exceptions in action controllers)?
Notices and warnings aren't (or shouldn't) be application fatal. Fatal errors do what they say on the tin and sometimes can't be caught. But, if you really need to, perhaps look into:
http://php.net/manual/en/function.set-error-handler.php