PHP try catch exceptions - php

Hello I have a code like that :
try
{
// Here I call my external function
do_some_work()
}
catch(Exception $e){}
The question is: If the do_some_work() has a problem and produce an Error this try catch will hide the error?

There are two types of error in PHP. There are exceptions, and there are errors.
try..catch will handle exceptions, but it will not handle errors.
In order to catch PHP errors, you need to use the set_error_handler() function.
One way to simplify things mught be to get set_error_handler() to throw an exception when you encounter an error. You'd need to tread carefully if you do this, as it has the potential to cause all kinds of trouble, but it would be a way to get try..catch to work with all PHP's errors.

If do_some_work() throws an exception, it will be catched and ignored.
The try/catch construct has no effect on standard PHP errors, only on exceptions.

produce a Fatal Error
No, catch can not catch Fatal Errors. You can not even with an error handler.
If you want to catch all other errors, have a look for ErrorException and it's dedicated use with set_error_handler:
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");
/* Trigger exception */
strpos();

Related

Include $_POST, $_GET, $_SERVER values in PHP Error Log

I have code like this
try {
header("Location: http://www.google.com\n-abc");
}
catch (Exception $e) {
error_log(print_r($_POST, true));
error_log(print_r($_GET, true));
error_log(print_r($_SERVER, true));
}
Without the try {} catch {} block, I can see the POST, GET and SERVER variables in my error_log, but with the try {} catch {} block, I only see the default PHP error.
Is there a way to show the POST, GET, and SERVER variables in a try {} catch {} block?
Is there a way to have PHP include POST, GET, and SERVER variables for ALL errors that get logged to file and not just wherever I have added error_log(print_r($_POST, true)); ....?
try/catch is for when you want to throw an exception to prevent php fatal errors from killing the page or to make debugging easier, generally speaking. This is how you would use a try/catch:
try {
if($a === true)
{
header("Location: http://www.google.com\n-abc");
}
else
{
throw new Exception('$a was not true');
}
}
catch (Exception $e) {
error_log(print_r($_POST, true));
error_log(print_r($_GET, true));
error_log(print_r($_SERVER, true));
echo $e->getMessage(); // $a was not true
}
The reason you don't see your error logs in the catch block in your example is because you never threw an exception so PHP will never look inside that catch block to log your variables.
If you simply want to get your example to work you'd just throw an exception to get PHP in that catch block:
try
{
throw new Exception('redirecting...');
}
catch (Exception $e)
{
error_log(print_r($_POST, true));
error_log(print_r($_GET, true));
error_log(print_r($_SERVER, true));
header("Location: http://www.google.com\n-abc");
}
That's just silly though :)
But default PHP functions like header will not throw exceptions.
If you want them to throw exceptions you will need to set the error handler to use ErrorException:
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
set_error_handler("exception_error_handler");
I think you have a few questions/issues here.
First, a try/catch block is used for Exceptions. The catch {} code is only executed if a Exception of the type specified is thrown.
Second, the header() function does not throw exceptions. Instead it just generates a PHP error directly.
Thirdly, to log those variables for all errors take a look at set_error_handler(), which should also take care of the above, second issue.
try/catch would only work if you're using an object that actually throws exception. header() is NOT an object and will NEVER throw an exception. Like I said in my answer to your previous version of this question, you need to set up a custom error handler.
That's how try/catch is supposed to work: the catch block executes when an exception is thrown in the try block (and only in that case).
The header() function may generate a warning if headers are already sent, but it will never throw an exception.
Answering your questions:
Your catch block is just fine but you need code that can actually throw exceptions (typically object-oriented code, but not necessarily). However, you can configure PHP to convert regular errors into exceptions if you use set_error_handler() to create a custom error handler and use throw inside of it.
Same as above: set_error_handler() and set_exception_handler().
Sounds like you want to have some extra information output to your log when an error is thrown. You should check out custom error handling in PHP. You can define specific ways to handle errors in your scripts and add functionality that is not there by default.PHP Set error handler

Ensure PHP shutdown function is called

I'm trying to catch as many errors as possible in PHP and properly handle them in a non-default way. My question is best illustrated in this example:
<?php
function errorHandler($errno, $errstr, $errfile, $errline){
echo "Error handler here <br>\n";
//throw new Exception($errstr);
}
function shutdownFunction() {
echo "Hi I'm in here <br>\n";
}
set_error_handler("errorHandler");
register_shutdown_function("shutdownFunction");
try {
$undefined->ok(); // causes some error
} catch(Exception $e) {
echo "Caught the exception <br>\n";
}
The result of running this code as a PHP program will indicate that errorHandler() is run, a PHP error is printed (if "display_errors" is set to "On"), and then shutdownFunction() is run.
The problem I'm having arises if I uncomment out that exception throw; I want to throw exceptions on PHP errors as often as possible. If I uncomment the throw statement out, then the error handler is called, which throws an exception thus causing a further error which results in shutdownFunction() not to be called.
It is my understanding that I can't make this error into a catchable exception; however, I would at least like to ensure that the shutdown function is called without restricting my ability to catch at least some php errors as exceptions (meaning I don't want to remove that throw statement in errorHandler()).
Is there some check in the errorHandler that I can do to check whether or not throwing it will cause shutdownFunction() to be bypassed?
Throw an exception from the error handler, then use set_exception_handler to handle uncaught exceptions.
So the way I'm solving this is to check if the $errstr parameter starts with "Undefined variable" - and if it does, then I'm not throwing the exception. I suppose if there are any other errors that have a similar issue, i'll do the same thing with those. I can't find a comprehensive list of php errors and what their affects are though, so it'll have to be ad hoc

How to catch all PHP errors?

I need a solution to catch all PHP fatal errors, exceptions, warnings, etc. and have a callback.
I want to display a friendly version of the error to the user and log that error.
I'm thinking about using a text file per day for logging error.
Any suggestion or PHP class (library)?
php method: set_error_handler might be what you are looking for.
More at: http://www.php.net/manual/en/function.set-error-handler.php
and at: http://php.net/manual/en/book.errorfunc.php
This makes almost all errors become catchable instance of ErrorException:
set_error_handler(function($errno, $errstr, $errfile, $errline ){
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
});
use it before of the code that can give errors, for instances at the very top of your php file or in a common header included
Limits: Severest errors (PHP engine, server, syntax) cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called compromise it.
But, if syntax is correct and server don't broke, these errors should not appear.
If needed, you could workaround it with the register_shutdown_function() and error_get_last()
As of PHP 8 the best way to catch any and all Exceptions is to catch the Throwable interface which "is the base interface for any object that can be thrown via a throw statement". So your code would look something like this.
try {
# code...
} catch (\Throwable $th) {
# code...
}
Try launch this web page, you should see "Message: Division by Zero".
// Set Error Handler
set_error_handler (
function($errno, $errstr, $errfile, $errline) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
);
// Trigger an exception in a try block
try {
$a = 3/0;
echo $a;
}
catch(Exception $e) {
echo 'Message: ' .$e->getMessage();
}
I quite like the error handling from the kohana framework. You'd have to do a bit of work to pull it out though.
http://kohanaframework.org/
It will allow you to do error logging to a file and email a recipient. It also enables you to redirect to your friendly error page.

What are some differences between error and exception in PHP?

I'm a beginner in PHP. So far, from the source I'm learning from, the only mechanism to trigger an exception is by writing a line that throws it.
throw new Exception('message')
Furthermore, on the code below, any exception won't be thrown, but an error will be raised.
try
{
$file = fopen('no such file.txt', 'r');
}
catch(Exception $e)
{
echo 'Exception: ' . $e->getMessage();
}
Please give me some explanations.
It seems this try..catch block is not so useful in PHP, unlike in Java or .NET.
By convention, the functions in the PHP core do not throw exceptions (the only exception is that constructors may throw exceptions, because there's no other way for them to properly signal error conditions).
Some differences:
Exceptions have types, and you can catch them according to their type. Errors only have an associated level (E_WARNING, E_STRICT, E_NOTICE, ...).
Exceptions can be caught at any point in the call stack, otherwise they go to a default exception handler. Errors can only be handled in the defined error handler.
"errors" are remains from the pre-oop era of php and are indeed hardly useful in the modern code. Fortunately, you can (actually, must) automatically convert most "errors" to exceptions. The magic is like this
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");
Once you've got this, your "fopen" snippet will work as expected. See http://php.net/manual/en/class.errorexception.php for more details/discussion.
It is not useful in this specific case, because fopen() doesn't throw an exception when it encounters an error. I think none of the core functions do.
If you are used to working with exceptions and want to work consistently with them, I think there is nothing speaking against using the ErrorException class to turn all errors into exceptions.
However, fopen() throws only a E_WARNING when it fails to open a file, so in your example, it would be easiest to test whether $file is false to see whether the operation failed.
I personally also like to do a file_exists() before fopen(), and react accordingly if the file is missing.

How to catch an "undefined index" E_NOTICE error in simpleTest?

I would like to write a test using simpleTest that would fail if the method I'm testing results in a PHP E_NOTICE "undefined index : foo".
I tried expectError() and expectException() without success. The simpleTest webpage indicate that simpleTest isn't able to catch compile time PHP errors, but E_NOTICE seems to be a run time error.
Is there a way to catch such an error and makes my test fail if so ?
That wasn't really easy but I finally managed to catch the E_NOTICE error I wanted. I needed to override the current error_handler to throw an exception that I will catch in a try{} statement.
function testGotUndefinedIndex() {
// Overriding the error handler
function errorHandlerCatchUndefinedIndex($errno, $errstr, $errfile, $errline ) {
// We are only interested in one kind of error
if ($errstr=='Undefined index: bar') {
//We throw an exception that will be catched in the test
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
return false;
}
set_error_handler("errorHandlerCatchUndefinedIndex");
try {
// triggering the error
$foo = array();
echo $foo['bar'];
} catch (ErrorException $e) {
// Very important : restoring the previous error handler
restore_error_handler();
// Manually asserting that the test fails
$this->fail();
return;
}
// Very important : restoring the previous error handler
restore_error_handler();
// Manually asserting that the test succeed
$this->pass();
}
This seems a little overly complicated having to redeclare the error handler to throw an exception just to catch it. The other hard part was correctly restoring the error_handler both when an exception was catched and no error occured, otherwise it just messes with SimpleTest error handling.
There really isn't a need to catch the notice error. One could also test the outcome of 'array_key_exists' and then proceed from there.
http://www.php.net/manual/en/function.array-key-exists.php
Test for false and have it fail.
You'll never catch it within the try-catch block, luckily we have set_error_handler():
<?php
function my_handle(){}
set_error_handler("my_handle");
echo $foo["bar"];
?>
You can do anything you want inside my_handle() function, or just leave it empty to silence the notice, although, it's not recommended. A normal handler should be like this:
function myErrorHandler($errno, $errstr, $errfile, $errline)
Many solutions to handling at sign E_NOTICE errors ignore all E_NOTICE errors. To ignore just errors due to use of at signs, do this in your set_error_handler callback function:
if (error_reporting()==0 && $errno==E_NOTICE)
return; // Ignore notices for at sign
An example of an important E_NOTICE that should not be ignored is this:
$a=$b;
because $b is undefined.

Categories