Welcome Guest, Not a member yet? Register   Sign In
Database functionality and Exceptions
#1

[eluser]Al James[/eluser]
Hi there...

Just a thought. In my old framework (self built) when a database query failed, it threw an exception and let the try and catch blocks attempt to recover. CI on the other hand simply displays a message and exits.

What do people think is the better behaviour? Personally I feel throwing an Exception is best, as if no try / catch blocks are used, it will be picked up by the default handler and exit anyway...

To do this, I changed the display_error function of the DB_driver class:

Code:
function display_error($error = '', $swap = '', $native = FALSE)
    {
        $LANG = new CI_Language();
        $LANG->load('db');

        $heading = 'MySQL Error';
        
        if ($native == TRUE)
        {
            $message = $error;
        }
        else
        {
            $message = ( ! is_array($error)) ? array(str_replace('%s', $swap, $LANG->line($error))) : $error;
        }

        //if ( ! class_exists('CI_Exceptions'))
        //{
        //    include_once(BASEPATH.'libraries/Exceptions'.EXT);
        //}
        
        //$error = new CI_Exceptions();
        //echo $error->show_error('An Error Was Encountered', $message, 'error_db');
        //exit;
        
        throw new Exception("Database error: ".$message);
    }

Its not very nice, a hack!

In fact, it appears that CI does not use Exceptions very well at all. It would be much nicer to have CI_Exception as a throwable object!
#2

[eluser]champs[/eluser]
Forget about try... catch, as long as there is PHP4 support.
#3

[eluser]Al James[/eluser]
Urg! Yes, I forgot about Exceptions not being in php4.

Hmmmm... I wonder if there is away around this?

I.e. Have the CI_Exceptions class actually throw an Exception if its running on PHP5? Like this:

* Create a CI_Exception class that extends Exception and holds the fields from CI_Exceptions->show_error
* Create a default exception handler that receieves the CI_Exception and does the same as the current CI_Exceptions->show_error function.
* Change CI_Exceptions->show_error so that if PHP5, throw a new Exception, if PHP4 just do as normal.

I understand that having 'throw' etc in the code igniter libraries would break PHP4 support. You could either:

A) Have a separate file for PHP4 and 5 (like Base4.php and Base5.php files)
B) eval('throw new Exception()'); (sneaky hey?)

What do ya all think?
#4

[eluser]Al James[/eluser]
Or, how about something like this:

Code:
function throw_exception($exception_class, $message)
{

    if (floor(phpversion()) < 5)
    {
    
        show_error($exception_class." : ".$message);
        
    } else {
        
        eval('throw new $exception_class($message);');
        
    }

}

function default_exception_handler($e)
{
    
    show_error($e->getMessage());
    
}

if (floor(phpversion()) >= 5) eval('set_exception_handler(\'default_exception_handler\');');

You could then throw Exceptions by:

Code:
throw_exception('Exception', 'An error occurred');

Not tested this in php4, but it should work! (I think!)
#5

[eluser]Jay Callicott[/eluser]
I like where you're going, myself I don't care about php 4 support but I would like it to throw exceptions if db_debug is set to FALSE, otherwise it can show the pretty error message.

I think a hack is probably the way to go. Can't fully follow your last example, why do you need evals?
#6

[eluser]Al James[/eluser]
Looking at my code only the first eval needs to be there.

Code:
function throw_exception($exception_class, $message)
{

    if (floor(phpversion()) < 5)
    {
    
        show_error($exception_class." : ".$message);
        
    } else {
        
        eval('throw new $exception_class($message);');
        
    }

}

function default_exception_handler($e)
{
    
    show_error($e->getMessage());
    
}

if (floor(phpversion()) >= 5) set_exception_handler('default_exception_handler');

The first eval is needed as otherwise the code would not run on php4 (throw is not a recognised language construct)...
#7

[eluser]Jay Callicott[/eluser]
This isn't exactly a global fix for all but something I might add to my shared install of CI is:

Code:
if ($CI->config->item('db_exception_handling') && $template == 'error_db') {
  throw new Exception("Database error, unable to continue.");    
}
Otherwise do normal stuff...

In the show_eror function in Exceptions.php. Unfortunately you can't override Exceptions and so I would have to hack it which is annoying bc it's one more thing I have to document so that I don't mess things over when I upgrade CI.

I've put in config values before is some of my libraries and thus far they've worked well for me. I am all php 5 and I would want to use this so that I can catch certain db errors.

This is tricky because if I really don't want to do a try catch for every db call I make, only the ones that are prone to db errors, in my case mssql queries are prone to timeouts and foreign key constraints cause more failures in queries now that im using foreign keys alot.

Darn this is tricky. I basically would want it to catch any uncaught exceptions with a nice pretty error message bc I'm not going to add a try/catch block to every single query. Hmmm.
#8

[eluser]Al James[/eluser]
Just do this! Wink

Code:
function default_exception_handler($e)
{
    
    show_error($e->getMessage());
    
}

set_exception_handler('default_exception_handler');




Theme © iAndrew 2016 - Forum software by © MyBB