Catching PDOException in lower layer and re-throwi

2020-07-20 04:32发布

问题:

Hello I am writing small PHP framework using PDO library. So at this moment I am facing with the exception catching problem. I want to catch thrown PDOException in lower layer and re-throw it as different exception object and bubble it up in such way to upper layer, hiding sensitive error information from users and displaying abstract useful messages for site admins and etc. In the example code (Mssql.class.php) I am trying to catch exception and re-throw as DBIException object when the connection to database cannot be established (e.g. bad hostname or username).

In the upper layer I try to catch DBIException (DBI.class.php) and re-throw it as CoreException object. In the last layer (SystemLoader.class.php) I am trying to catch CoreException and print corresponding message. As you see from the code the main initialization class (SystemLoader.class.php) and init() method are executed from index.php but if PDOException error occurs in lower layers I got Fatal error: Uncaught exception 'PDOException' not CoreException with message "System couldn't load specified resources" as I am expecting. But If I put System::init() in index.php between try..catch block the exception is caught but not the DBIException or CoreException only PDOException.

It looks like that catching mechanism somehow is not responding to try...catch blocks in lower level and the other thing is that I don't want to use try...catch blocks in index.php file simply I don't want to make this file structure complex. I read many info in the internet and understood the concept of Exception handling but at this moment I don't know where I am doing mistake. Should I set custom Exception Handler in SystemLoader.class.php or use some other technics

index.php

<?php
    require_once("SystemLoader.class.php");
    System::init();                   //initializing system params and other stuff
?>

SystemLoader.class.php

<?php
    require_once("DBIException.class.php");

    class SystemLoader
      {
        static function init()
          {
            try
               {
                 DBI::loadDBDriver("mssql");    //trying to load DB driver
               }
            catch(CoreException $e)
               {
                 echo "System couldn't load specified resources";
               }
         }
      }
?>

DBI.class.php

<?php

require_once("CoreException.class.php");

class DBI
  {    
    private $dbh;

    public static function loadDBDriver($dbDriver)
      {
        if($dbDriver = "mssql")
          {
            try 
               {
                 return new Mssql;
               } 
            catch (DBIException $e) 
               {
                 throw new CoreException($e)
               }
          }
        elseif($dbDriver = "mysql")
          {
            try 
               {
                 return new Mysql;
               } 
            catch (DBIException $e) 
               {
                 throw new CoreException($e)
               }
          }
      }

    public function setDBHandle($dbh)
     {
        $this->dbh = $dbh;
        $this->dbh->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_EMPTY_STRING);
        $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
     }
 }

Mssql.class.php

<?php
    require_once("DBIException.class.php");

class Mssql extends DBI
  { 
    public function __construct()
      {
       try 
          {
             $dbh=new PDO("dblib:host=192.168.0.1;Database=dbName", "user", "pass");
             parent::setDBHandle($dbh);
          }
       catch(PDOException $e)         //PDOException is not catched at this point
         {
             throw new DBIException($e);    /re-throw as new Exception object
         }
      }
  }
?>

CoreException.class.php

<?php
   class CoreException extends Exception {}
?>

DBIException.class.php

<?php
   class DBIException extends Exception {}
?>