0

I'm running into an issue where my PHP project is not catching exceptions when I use a Try Catch Block. When an exception is thrown PHP will still display the exception's error message and will end execution of the PHP script. I have narrowed it down to the fact that I have a custom PHP error handler I built. Once I remove my custom PHP handler then TRY CATCH blocks work normally again. Removing the custom error handler is not an option unfortunately. Please see code below:

    use \ErrorException; 
    use \BrowserDetection;
    use \DateTime;
    use \DateTimeZone; 
    use \Database; 

    define("DEBUG_ON", "DEBUG_ON");
    define("DEBUG_OFF", "DEBUG_OFF");

    ErrorHandler::register(); 

    class ErrorHandler
    {
        public static function register() {
            global $_WEBCONFIG; 
            if(!isset($_COOKIE['XDEBUG_SESSION'])) {
                if($_WEBCONFIG['DEBUG_SETTING'] == DEBUG_OFF || stristr($_SERVER['PHP_SELF'], 'error.php')) {
                    ini_set('display_errors', '0');
                    error_reporting(0);
                } else {
                    ini_set('display_errors', '1');
                    switch ($_WEBCONFIG['DEBUG_WARNING_LEVEL']) {
                        case 1:
                            error_reporting(E_ERROR | E_PARSE);
                            set_error_handler(array("Base\Handlers\ErrorHandler", "error_handler"), E_ERROR | E_PARSE);
                            break;
                        case 2:
                            error_reporting(E_ERROR | E_WARNING | E_PARSE);
                            set_error_handler(array("Base\Handlers\ErrorHandler", "error_handler"), E_ERROR | E_WARNING | E_PARSE);
                            break;
                        case 3:
                            error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
                            set_error_handler(array("Base\Handlers\ErrorHandler", "error_handler"), E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
                            break;
                        case 4:
                            error_reporting(E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
                            set_error_handler(array("Base\Handlers\ErrorHandler", "error_handler"), E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
                            break;
                        default:
                            error_reporting(E_ALL);

                            set_error_handler(array("Base\Handlers\ErrorHandler", "error_handler"), E_ALL);
                            register_shutdown_function(array("Base\Handlers\ErrorHandler", "fatal_error_handler"));
                    }
                    set_exception_handler(array("Base\Handlers\ErrorHandler", "exception_handler"));
                }
            }
        }

        public static function log_exception($exception) {
            require_once($_SERVER['DOCUMENT_ROOT'] . "/library/classes/class_browser_detection.php");
            global $_WEBCONFIG, $siteConfig;

            $browser = new BrowserDetection();
            $userBrowserName = $browser->getBrowser();
            $userBrowserVer = $browser->getVersion();
            $userBrowserPlatform = $browser->getPlatform();
            $userBrowserIsMobile = $browser->isMobile() == "" ? "No" : "Yes";
            $userBrowserIsRobot = $browser->isRobot() == "" ? "No" : "Yes";
            $companyName = isset($siteConfig['Company_Name']) ? $siteConfig['Company_Name'] : '';
            $userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'Unknown';
            $ip = isset($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : 'N/A';
            $today = new DateTime("now", new DateTimeZone('US/Central'));
            $date = $today->format("F j, Y g:i a"); 
            $username = isset($_SESSION['member_username']) ? $_SESSION['member_username'] : (isset($_SESSION['user_username']) ? $_SESSION['user_username'] : null); 

            // Remove ErrorException Trace Referenceing Error Handler & Get Error Type
            if(get_class($exception) == "Base\Handlers\CoreErrorException") {   
                $sTraceArray = array_slice(explode("\n", $exception->getTraceAsString()), 1);
                $traceString = implode($sTraceArray); 
                $type = $exception->getExceptionType(); 
            } else {
                $traceString = $exception->getTraceAsString(); 
                $type = 'E_' . strtoupper(get_class($exception));
            }

            $message = '<p><b>EXCEPTION TYPE</b>: ' . $type . PHP_EOL;  
            $message .= '<br /><b>MESSAGE: </b>' . $exception->getMessage(). PHP_EOL;
            $message .=   '<br /><b>SITE PAGE: </b>' . $_SERVER['ABSOLUTE_URI']. PHP_EOL;
            $message .=  '<br /><b>LOCATION: </b>' . $exception->getFile(). PHP_EOL;
            $message .= '<br /><b>LINE NUMBER: </b>' . $exception->getLine(). PHP_EOL;
            if(!is_null($username)) {
                $message .=  '<br /><b>USERNAME: </b>' . $username . PHP_EOL;
            }
            $message .=  '<br /><b>USER AGENT: </b>' . $userAgent . PHP_EOL;
            $message .=  '<br /><b>OPERATING SYSTEM: </b>' . $userBrowserPlatform . PHP_EOL;
            $message .=  '<br /><b>BROWSER: </b>' . $userBrowserName . ' ' . $userBrowserVer . PHP_EOL;
            $message .=  '<br /><b>MOBILE: </b>' . $userBrowserIsMobile . PHP_EOL;
            $message .=  '<br /><b>ROBOT: </b>' . $userBrowserIsRobot . PHP_EOL;
            $message .=  '<br /><b>IP ADDRESS: </b>' . $ip  . PHP_EOL;
            $message .=  '<br /><b>ERROR TIME: </b>' . $date . "\n</p>" . PHP_EOL;;
            $message .=  '<p><b>' . str_repeat("-", 75) . ' PHP STACK TRACE ' . str_repeat("-", 75) . '</b>' . PHP_EOL;
            $message .= str_replace('#', '<br />#', $traceString) . "</p>\n". PHP_EOL;;

            if(Database::hasConnection()) {
                $trace = Database::quote_smart($traceString);
                $filepath = Database::quote_smart($exception->getFile());
                $errLine = (int) $exception->getLine();
                $errNo = (int) $exception->getCode();
                $errStr = Database::quote_smart($exception->getMessage());
                if(!is_null($username)) {
                    if(isset($_SESSION['member_prov_num'])) {
                       $providerNo = $_SESSION['member_prov_num']; 
                       $sql = "INSERT INTO `tbl_error_log` (`el_type`, `el_code`, `el_message`, `el_url`, `el_file_path`, `el_line_number`, `el_user_agent`, `el_ip_address`, `el_details`, `el_username`, `el_provider_number`)
                               VALUES ('$type', '$errNo', '$errStr', '{$_SERVER['ABSOLUTE_URI']}', '$filepath', '$errLine', '$userAgent', '$ip', '$trace', '$username', '$providerNo');";
                    } else {
                        $sql = "INSERT INTO `tbl_error_log` (`el_type`, `el_code`, `el_message`, `el_url`, `el_file_path`, `el_line_number`, `el_user_agent`, `el_ip_address`, `el_details`, `el_username`)
                            VALUES ('$type', '$errNo', '$errStr', '{$_SERVER['ABSOLUTE_URI']}', '$filepath', '$errLine', '$userAgent', '$ip', '$trace', '$username');";
                    }
                } else {
                    $sql = "INSERT INTO `tbl_error_log` (`el_type`, `el_code`, `el_message`, `el_url`, `el_file_path`, `el_line_number`, `el_user_agent`, `el_ip_address`, `el_details`)
                            VALUES ('$type', '$errNo', '$errStr', '{$_SERVER['ABSOLUTE_URI']}', '$filepath', '$errLine', '$userAgent', '$ip', '$trace');";
                }
                Database::ExecuteRaw($sql);
            }

            $headers  = 'MIME-Version: 1.0' . "\r\n";
            $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
            $headers .= 'From: ' . $companyName .' <[email protected]>' . "\r\n";
            if($_WEBCONFIG['DEBUG_SETTING'] == DEBUG_ON) {
                $recipients = str_replace(";",",",$_WEBCONFIG['DEVELOPER_EMAIL']);
                mail($recipients, 'Error Message', $message, $headers);
            }
            return $message; 
        }

        public static function error_handler($errNo, $errStr, $errFile, $errLine)
        {
            // Convert PHP Error Into Exception
            self::exception_handler(new CoreErrorException($errStr, $errNo, $errFile, $errLine));
        }

        public static function fatal_error_handler() {
            $last_error = error_get_last();
            if(isset($last_error['type']) 
                || $last_error['type'] ===  E_ERROR 
                || $last_error['type'] ===  E_CORE_ERROR
                || $last_error['type'] ===  E_CORE_WARNING
                || $last_error['type'] ===  E_COMPILE_ERROR
                || $last_error['type'] ===  E_COMPILE_WARNING) {
                self::exception_handler(new CoreErrorException($last_error['message'], $last_error['type'], $last_error['file'], $last_error['line']));
            } 
        } 

        public static function exception_handler($exception) {

            global $_WEBCONFIG;

            $message = self::log_exception($exception); 
            if($_WEBCONFIG['FRIENDLY_ERRORS'] == "Off" || ($_WEBCONFIG['FRIENDLY_ERRORS'] == "Local" && ($ip == $_WEBCONFIG["LOCAL_IP"] || '127.0.0.1'))) {
                header_remove('content-type'); 
                header('content-type: text/html; charset=UTF-8');
                if (ob_get_length() > 0) { ob_end_clean(); }
                self::print_header();
                print $message;
                self::print_footer();
                exit();
            } else {
                $errorPage = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : '';
                redirect($_WEBCONFIG['CUSTOMERRORS']['DEFAULTREDIRECT']['500'] . '?path=' . $errorPage);
            }
        }

        private static function print_header() {
            global $_WEBCONFIG, $siteConfig;

            print '<!doctype html><html xmlns="http://www.w3.org/1999/xhtml"><head><title>PHP Page Error</title>';
            print '<style>body { background-color: #fcfcfc; color: #333333; margin: 0; padding:0; } h1 { font-size: 1.5em; font-weight: normal; background-color: #9999cc; min-height:2em; line-height:2em; border-bottom: 1px inset black; margin: 0; } h1, p { padding-left: 10px; } code.url { background-color: #eeeeee; font-family:monospace; padding:0 2px;}</style>';
            print '</head><body>';
            print '<div class="content" style="left: 50px;">';
            print "<h1>PHP Page Error</h1>";

        }

        private static function print_footer() {
            print '</div></body></html>';
        }
    }

    class CoreErrorException extends ErrorException {

        protected $errorType; 

        public function __construct($errStr, $errNo, $errFile, $errLine) {
            parent::__construct($errStr, 0, $errNo, $errFile, $errLine);
            switch ($this->code) {
                case E_ERROR:
                    $this->errorType = "E_ERROR";
                    break; 
                case E_WARNING :
                    $this->errorType = "E_WARNING";
                    break; 
                case E_PARSE :
                    $this->errorType = "E_PARSE";
                    break; 
                case E_NOTICE:
                    $this->errorType = "E_NOTICE";
                    break; 
                case E_CORE_ERROR :
                    $this->errorType = "E_CORE_ERROR";
                    break; 
                case E_CORE_WARNING :
                    $this->errorType = "E_CORE_WARNING";
                    break; 
                case E_COMPILE_ERROR:
                    $this->errorType = "E_COMPILE_ERROR";
                    break; 
                case E_COMPILE_WARNING :
                    $this->errorType = "E_COMPILE_WARNING";
                    break; 
                case E_USER_ERROR :
                    $this->errorType = "E_USER_ERROR";
                    break; 
                case E_USER_WARNING:
                    $this->errorType = "E_USER_WARNING";
                    break; 
                case E_USER_NOTICE :
                    $this->errorType = "E_USER_NOTICE";
                    break; 
                case E_STRICT :
                    $this->errorType = "E_STRICT";
                    break; 
                case E_RECOVERABLE_ERROR:
                    $this->errorType = "E_RECOVERABLE_ERROR";
                    break; 
                case E_DEPRECATED :
                    $this->errorType = "E_DEPRECATED";
                    break; 
                case E_USER_DEPRECATED :
                    $this->errorType = "E_USER_DEPRECATED";
                    break; 
                default:
                    $this->errorType = "E_CORE";
            }
        }
        public function getExceptionType() {
            return $this->errorType . '_EXCEPTION'; 
        }
    }
    ?>

I have also included an example of a catch block where the code is not being caught:

    try {
        $response = $client->GetAllOrdersByOrderNo($request);
    } catch (Exception $e) {
        $response = null; 
    }

Class Calling Exception

<?php
namespace Base\Members\Library; 
use \SoapClient; 
use \SimpleXMLElement; 

class MembershipAPI
{
    public static function getOrderByOrderNo($orderNo) { 
        $client = new SoapClient("https://bah.foo.com/members/Services/Orders.svc?wsdl");
        $request = array(array()); 
        $request['request']['OrderNo'] = $orderNo; 
        try {
            $response = $client->GetAllOrdersByOrderNo($request);
        } catch (Exception $e) {
            // This code is never set
            $response = null; 
        }

        /*if (response.OperationStatus != Orders.ExternalServiceResponseStatus.Success)
        {
            throw new Exception(response.OperationErrors[0]);
        } */ 
        return isset($response->GetAllOrdersByOrderNoResult->Orders->Order) ? $response->GetAllOrdersByOrderNoResult->Orders->Order : null; 
    }
}
4
  • Where is the GetAllOrdersByOrderNo implementation that is throwing the new Exception (throw new Exception("some error"))? and does the Class it's throwing implement \Exception as it is not required in PHP so you can't catch an exception if it's not child class of \Exception with catch(\Excpetion $e). Commented Dec 18, 2017 at 14:30
  • I've edited it and added it in for you to view. However no exceptions can be caught even outside this code, even if its in the global namespace. Commented Dec 18, 2017 at 14:37
  • you don't get PHP exceptions from SoapClient Class RPC call as the SoapClient did not exception E.G $client->GetAllOrdersByOrderNo($request); will never throw an exception even if the remote system throws an exception it should output the exception or error to you, you then have to parse the result to check if it's in error state. also to note PHP Programming errors are not exceptions in PHP they are errors, Can you provide a demo of a failed state response echo "<pre>".print_r($response, true)."</pre>"; Commented Dec 18, 2017 at 14:42
  • I can but I think your getting too hung up on the SoapClient class. This is just an example, any class throwing an exception cannot be caught by a try catch. so if I simply do a throw new Exception("Hello World") it still doesn't get caught. Commented Dec 18, 2017 at 19:16

1 Answer 1

8
+50
 try {
     $response = $client->GetAllOrdersByOrderNo($request);
 } catch (Exception $e) {
     // This code is never set
     $response = null; 
 }

You are in namespace Base\Members\Library.

The block is catching Base\Members\Library\Exception

Try catching \Exception in the global namespace instead.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.