Showing posts with label PHP Exceptions. Show all posts
Showing posts with label PHP Exceptions. Show all posts

Monday, 24 September 2018

Get code line and file name that's executing processing the current function in PHP

function log() {
    try {
        $bt = debug_backtrace();
        $fileAndLine = "";
        for ($i = 0; $i < 10; $i++) {
            $row = $bt[$i];
            if (isset($row["file"]) && isset($row["line"])) {
                $fileAndLine = $row["file"] . "::" . $row["line"];
                $i = 50;
            }
        }
        return $fileAndLine;
    }
    catch (Exception $ex) {
        return "";
    }
}

Tuesday, 11 September 2018

Catch uncaught exceptions with PHP

This is the third in a series of posts about exception handling in PHP and looks at how to specify a default exception handler. The default handler is called for any exceptions that occur which are not enclosed in a try..catch block.

Normally catch exceptions in a try..catch block

If an exception is handled inside a try..catch block it will not result in an error. For example no error will be output using the code below, unless you choose to echo something in the catch section.
try {
    throw new Exception("This is an example exception");
}
catch(Exception $e) {
   
}

When an exception occurs that is not in a try..catch block

However, if the exception occurs and is not inside a try..catch block:
throw new Exception("This is an example exception");
then an error will be echoed to standard output:
Fatal error: Uncaught exception 'Exception' with message 'This is an example exception' in /common/websites/test/exceptions-example.php:5
Stack trace:
#0 {main}
  thrown in /common/websites/test/exceptions-example.php on line 5

Creating an exception handler

Normally you'd put something which could possibly have an exception into a try..catch block but it's possible instead to handle all exceptions with a specified exception handler using the set_exception_handler() function.
This may not necessarily be the best practise but it is possible to do and may help catch out errors in your code which you may not have realised could throw an exception.
This is done by defining an exception handling function and setting it like so:
set_exception_handler('my_exception_handler');

function my_exception_handler($e) {
    // do some erorr handling here, such as logging, emailing errors
    // to the webmaster, showing the user an error page etc
}
Now when any exception occurs that is not handled by a try..catch block it will run the my_exception_handler() function. Obviously you can call your own exception handler whatever you want it to be.

Exception Series

This is the third post in a weekly series of seven about PHP exceptions. Read the previous post "PHP Exceptions - available information", the next post"Replace error reporting with exception handlers with PHP" and use the links below to subscribe to my RSS feed, by email, or follow me on Twitter or Facebook to keep up to date with my daily postings.


Related posts:

Replace error reporting with exception handlers with PHP

As part of a series of posts about PHP exception handling, this post looks at how to make regular errors use exception model. Normally only the newer object-oriented extensions throw exceptions but it is possible to make all errors throw an exception instead using set_error_handler.

Normal behavior

The normal behavior for a normal error is to show an error message which cannot be handled by the try...catch syntax. For example, if error reporting is E_ALL and we try to access a variable which has not yet been set:
error_reporting(E_ALL);
echo $x;
This is what will be displayed:
Notice: Undefined variable: x in [filename] on line [line number]

Bind errors to the ErrorException handler

Instead of this default error behavior, errors can be bound to the ErrorException handler like so:
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");
What this is doing is replacing the default error handler with our own function which in turn throws an ErrorException. Now when we try to use the same variable above that has not been set an exception will be thrown, looking something like this:
Fatal error: Uncaught exception 'ErrorException' with message 'Undefined variable: x' in [filename]:[line number]
Stack trace:
#0 [filename]([line number]): exception_error_handler()
#1 {main}
  thrown in [filename] on line [line number]
This could now instead be handled inside a try..catch block like so:
try {
    echo $x;
}
catch(Exception $e) {
   
}
Obviously you wouldn't be trying to catch such a trivial exception example; it's just to illustrate the other examples on this page which deal with a fairly trivial error. You could then potentially use an exception handler to deal with these sorts of exceptions, instead of having to have separate error handlers and exception handlers.

Exception Series

This is the fourth post in a weekly series of six about PHP exceptions. Read the previous post "Catch uncaught exceptions with PHP", the next post "Extend PHP's exception object" and use the links below to subscribe to my RSS feed, by email, or follow me on Twitter or Facebook to keep up to date with my daily postings.

Related posts:

Extend PHP's exception object

PHP's Exception object can be extended (just as any class can be that is not declared final) which means different exception types can be thrown that handle the exception differently.

Extending Exception

The following example extends Exception with a new class called MyException. When MyException is run it does some logging and sends an email. Exactly what the extended exception class does is up to you depending on the circumstances where it is required.
class MyException extends Exception {

    public function __construct($message = null, $code = 0) {
        parent::__construct($message, $code);
        $this->sendNotifications();
        $this->logError();
    }

    protected function sendNotifications() {
        // send some notifications here
    }

    protected function logError() {
        // do some logging here
    }

}

Throwing MyException

To cause an exception of the class MyException to occur simply do this in your code at the point where the exception needs to occur, substituting the message and error code for something a little more meaningfully than is shown in my example:
throw new MyException('This is a really bad error', 123);
As usual, the code throwing the exception should be contained within a try..catch block to avoid a fatal error message and stack trace being renderd. See my first post about PHP Exceptions for more details about catching these.

Exception Series

This is the fifth post in a weekly series of seven about PHP exceptions. Read the previous post "Replace error reporting with exception handlers with PHP", the next post "Catch mutiple exception types with PHP" and use the links below to subscribe to my RSS feed, by email, or follow me on Twitter or Facebook to keep up to date with my daily postings.

Related posts:

Catch mutiple exception types with PHP

PHP's try..catch can be used to catch multiple exception types. If the try block could cause one of several different exceptions they can each be handled separately with their own catch section.

Example exceptions

Here's some example exceptions that have been defined for the purposes of this example:
class FooException extends Exception {
    public function __construct($message = null, $code = 0) {
        // do something
    }
}

class BarException extends Exception {
    public function __construct($message = null, $code = 0) {
        // do something
    }
}

class BazException extends Exception {
    public function __construct($message = null, $code = 0) {
        // do something
    }
}

Handling multiple exceptions

It's very simple - there can be a catch block for each exception type that can be thrown:
try {
    // some code that might trigger a Foo/Bar/Baz/Exception
}
catch(FooException $e) {
    // we caught a foo exception
}
catch(BarException $e) {
    // we caught a bar exception
}
catch(BazException $e) {
    // we caught a baz exception
}
catch(Exception $e) {
    // we caught a normal exception
    // or an exception that wasn't handled by any of the above
}
If an exception is thrown that is not handled by any of the other catch statements it will be handled by the catch(Exception $e) block. It does not necessarily have to be the last one.

Exception Series

This is the six post in a weekly series of seven about PHP exceptions. Read the previous post "Extend PHP's exception object", the last post in the series "Exiting from within a PHP exception" and use the links below to subscribe to my RSS feed, by email, or follow me on Twitter or Facebook to keep up to date with my daily postings.

Related posts:

Exiting from within a PHP exception

This is the final post in my series about PHP exceptions and looks at how when an exception occurs, script execution may continue depending on how the exception is handled.

Examples

I've been using PHP's PDO library recently instead of the more traditional approach of using the database specific functions such as the mysql_* functions. PDO is an object oriented approach and uses the exception model to throw errors. It is a useful example to show how execution will continue even if an exception is thrown when attempting to connect to the database.
The two examples below attempt to establish a connection to a MySQL database using a database, login name and password that do not exist, defined as follows:
$dsn = "mysql:host=localhost;dbname=fakedb";
$username = "fakeuser";
$password = "fakepassword";
The first example doesn't bother attempting to catch the exception and execution will halt before getting to the line 'echo "code continues here\n";':
$pdo = new PDO($dsn, $username, $password);
echo "code continues here\n";
This will output the following:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[28000] [1045] Access denied for user 'fakeuser'@'localhost' (using password: YES)' in /common/websites/test/exceptions-example.php:7
Stack trace:
#0 /common/websites/test/exceptions-example.php(7): PDO->__construct('mysql:host=loca...', 'fakeuser', 'fakepassword')
#1 {main}
  thrown in /common/websites/test/exceptions-example.php on line 7
Because the exception is not handled, the error message will be displayed and execution will halt. Ideally we do not want to display error messages such as the above.
On the other hand, if we handle the exception without ending the script using exit or die:
try {
    $pdo = new PDO($dsn, $username, $password);
}
catch(Exception $e) {
    echo "Exception\n";
}
echo "code continues here\n";
then this is what will be echoed:
Exception
code continues here
In the event of an exception occurring that means the script cannot continue to run, such as not being able to connect to the database, execution should halt (after doing whatever logging or emailed notifications etc is required).
This is often as simple as using exit to end the script's execution like so:
try {
    $pdo = new PDO($dsn, $username, $password);
}
catch(Exception $e) {
    // do some logging and/or notification here
    exit;
}

The PHP Exception Series

This concludes my series on PHP exceptions. See the related posts below for earlier posts in the series.

Related posts:

PHP Exceptions - available information

This post is part of a series about PHP exceptions and exception handling; the first post gave a basic overview of how they work and this one shows the information that is available from the exception object when an exception is caught.

Example Code

The following is an example function that will throw an exception. Then folllows a try .. catch block which will catch the exception. It's in the catch() block that we have access to the information stored in the exception object.
<?php

function throw_an_exception() {
    throw new Exception("This is an example exception", 100); 
}

try {
    throw_an_exception();
}
catch(Exception $e) {
    // exception handling goes here
}

Available information

The exception object has several pieces of information available which can be retrieved through function calls. Each section below covers the various calls and shows example output for the above example. The echo $e->getFile() etc calls in the examples below occur within the catch() { } block above where it says "// exception handling goes here".

$e->getFile()

This contains the name of the file in which the exception occurred. This (or any of the other items below) could be sent in an email, logged to a file etc. In these examples I will echo them.
echo $e>getFile();
Output:
/var/www/test/exceptions-example.php

$e->getLine()

This contains the line number the exception occured on.
echo $e->getLine()
Output:
4

$e->getCode()

This contains the error code. In the example above it was the second parameter passed when "throw new Exception" was called. The meaning of the code will depend on the exception thrown.
echo $e->getCode();
Output:
100

$e->getMessage()

This contains the error message which is usually more meaningful than the error code. In the above example this was the first parameter passed when the exception was thrown.
echo $e->getMessage();
Output:
This is an example exception

$e->getTrace();

getTrace returns a backtrace to show the order of function calls that led to the exception in reverse order with the most recent function call first. In the above example there was only one function called to get the exception so the array returned from print_r returns just a single element. To return the information from print_r as a string for logging or email, pass true as the second parameter to the print_r call.
print_r($e->getTrace())
Output:
Array
(
    [0] => Array
        (
            [file] => /var/www/test/exceptions-example.php
            [line] => 8
            [function] => throw_an_exception
            [args] => Array
                (
                )

        )

)

$e->getTraceAsString()

An alternative to the getTrace method is getTraceAsString() which returns the same sort of information as debug_print_backtrace() but in a string instead of to standard output. This is a more condensed version than getTrace.
echo $e->getTraceAsString()
Output:
#0 /var/www/test/exceptions-example.php(8): throw_an_exception()
#1 {main}

$e->__toString()

__toString() returns a string containing the error message, file and line number, and the backtrace returned from getTraceAsString().
echo $e->__toString()
Output:
exception 'Exception' with message 'This is an example exception' in /var/www/test/exceptions-example.php:4
Stack trace:
#0 /var/www/test/exceptions-example.php(8): throw_an_exception()
#1 {main}

Exception Series

This is the second post in a weekly series of seven about PHP exceptions. Read the previous post "PHP Exceptions" and next post "Catch uncaught exceptions with PHP" and use the links below to subscribe to my RSS feed, by email, or follow me on Twitter or Facebook to keep up to date with my daily postings.

Related posts:

Thursday, 4 September 2014

Error and Exception handling in PHP

Error handling is the process of catching errors raised by your program and then taking appropriate action. If you would handle errors properly then it may lead to many unforeseen consequences.
Its very simple in PHP to handle an errors.

Using die() function:

While wirting your PHP program you should check all possible error condition before going ahead and take appropriate action when required.
Try following example without having /tmp/test.xt file and with this file.
<?php
if(!file_exists("/tmp/test.txt"))
 {
 die("File not found");
 }
else
 {
 $file=fopen("/tmp/test.txt","r");
 print "Opend file sucessfully";
 }
 // Test of the code here.
?>
This way you can write an efficient code. Using abive technique you can stop your program whenever it errors out and display more meaningful and user friendly meassage.

Defining Custom Error Handling Function:

You can write your own function to handling any error. PHP provides you a framwork to define error handling function.
This function must be able to handle a minimum of two parameters (error level and error message) but can accept up to five parameters (optionally: file, line-number, and the error context):

Syntax

error_function(error_level,error_message, error_file,error_line,error_context);
 
Parameter Description
error_level Required - Specifies the error report level for the user-defined error. Must be a value number.
error_message Required - Specifies the error message for the user-defined error
error_file Optional - Specifies the filename in which the error occurred
error_line Optional - Specifies the line number in which the error occurred
error_context Optional - Specifies an array containing every variable and their values in use when the error occurred

Possible Error levels

These error report levels are the different types of error the user-defined error handler can be used for. These values cab used in combination using | operator
Value Constant Description
1 E_ERROR Fatal run-time errors. Execution of the script is halted
2 E_WARNING Non-fatal run-time errors. Execution of the script is not halted
4 E_PARSE Compile-time parse errors. Parse errors should only be generated by the parser.
8 E_NOTICE Run-time notices. The script found something that might be an error, but could also happen when running a script normally
16 E_CORE_ERROR Fatal errors that occur during PHP's initial startup.
32 E_CORE_WARNING Non-fatal run-time errors. This occurs during PHP's initial startup.
256 E_USER_ERROR Fatal user-generated error. This is like an E_ERROR set by the programmer using the PHP function trigger_error()
512 E_USER_WARNING Non-fatal user-generated warning. This is like an E_WARNING set by the programmer using the PHP function trigger_error()
1024 E_USER_NOTICE User-generated notice. This is like an E_NOTICE set by the programmer using the PHP function trigger_error()
2048 E_STRICT Run-time notices. Enable to have PHP suggest changes to your code which will ensure the best interoperability and forward compatibility of your code.
4096 E_RECOVERABLE_ERROR Catchable fatal error. This is like an E_ERROR but can be caught by a user defined handle (see also set_error_handler())
8191 E_ALL All errors and warnings, except level E_STRICT (E_STRICT will be part of E_ALL as of PHP 6.0)
All the above error level can be set using following PHP built-in library function where level cab be any of the value defined in above table.
int error_reporting ( [int $level] )
Following is the way you can create one error handling function:
<?php
function handleError($errno, $errstr,$error_file,$error_line)
{ 
 echo "<b>Error:</b> [$errno] $errstr - $error_file:$error_line";
 echo "<br />";
 echo "Terminating PHP Script";
 die();
}
?>
Once you define your custom error handler you need to set it using PHP built-in library set_error_handler function. Now lets examine our example by calling a function which does not exist.
<?php
error_reporting( E_ERROR );
function handleError($errno, $errstr,$error_file,$error_line)
{
 echo "<b>Error:</b> [$errno] $errstr - $error_file:$error_line";
 echo "<br />";
 echo "Terminating PHP Script";
 die();
}
//set error handler
set_error_handler("handleError");

//trigger error
myFunction();
?>

Exceptions Handling:

PHP 5 has an exception model similar to that of other programming languages. Exceptions are important and provides a better control over error handling.
Lets explain thre new keyword related to exceptions.
  • Try - A function using an exception should be in a "try" block. If the exception does not trigger, the code will continue as normal. However if the exception triggers, an exception is "thrown".
  • Throw - This is how you trigger an exception. Each "throw" must have at least one "catch".
  • Catch - - A "catch" block retrieves an exception and creates an object containing the exception information.
When an exception is thrown, code following the statement will not be executed, and PHP will attempt to find the first matching catch block. If an exception is not caught, a PHP Fatal Error will be issued with an "Uncaught Exception ...
  • An exception can be thrown, and caught ("catched") within PHP. Code may be surrounded in a try block.
  • Each try must have at least one corresponding catch block. Multiple catch blocks can be used to catch different classes of exeptions.
  • Exceptions can be thrown (or re-thrown) within a catch block.

Example:

Following is the piece of code, copy and paste this code into a file and verify the result.
<?php
try {
    $error = 'Always throw this error';
    throw new Exception($error);

    // Code following an exception is not executed.
    echo 'Never executed';

} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

// Continue execution
echo 'Hello World';
?>
In the above example $e->getMessage function is uded to get error message. There are following functions which can be used from Exception class.
  • getMessage()- message of exception
  • getCode() - code of exception
  • getFile() - source filename
  • getLine() - source line
  • getTrace() - n array of the backtrace()
  • getTraceAsString() - formated string of trace

Creating Custom Exception Handler:

You can define your own custome excpetion handler. Use following function to set a user-defined exception handler function.
string set_exception_handler ( callback $exception_handler )
Here exception_handler is the name of the function to be called when an uncaught exception occurs. This function must be defined before calling set_exception_handler().

Example:

<?php
function exception_handler($exception) {
  echo "Uncaught exception: " , $exception->getMessage(), "\n";
}

set_exception_handler('exception_handler');

throw new Exception('Uncaught Exception');

echo "Not Executed\n";
?>