How to save $DB errors to a variable

How to save $DB errors to a variable

by Lloyd D -
Number of replies: 9

I'd like to able to echo the error message given if a $DB fails. For example, if the statement, "$DB->update_record...." fails then I'd like to be able to take its error message, store it in a variable or file and display to the user

Average of ratings: -
In reply to Lloyd D

Re: How to save $DB errors to a variable

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

If you just want to see errors, turn on Debugging (set it to Developer level).

If you want something more fancy, then DB errors are thrown as exceptions, which you can catch, or they are handled by a default exception hander.

In reply to Tim Hunt

Re: How to save $DB errors to a variable

by Lloyd D -

Yes, how can I take the exception and store it in a variable? I want to catch the exception and store it to a database under a specified column. The table in which it is stored in serves as a log of the errors

In reply to Lloyd D

Re: How to save $DB errors to a variable

by Jonathan P. -

Using try / catch, it's quiet straight forward. Here's an example with a query giving you the new messages for the current user.

 try{

     $yourQuery = $DB->count_records_sql("        

                                      SELECT COUNT(m.useridfrom) FROM mdl_user u, mdl_message m
                                      WHERE m.useridto = '$USER->id'
                                      AND u.id = m.useridfrom
                               ");
     }catch(Exception $e){
           // the potential error is stored in $e, just do whatever you want with it.

     }


CAUTION :

I wouldn't use try / catch for basic error reporting. You would be revealing some system internals to a potential attacker when the site goes live (if you choose to display it to the user of course). There are other reasons like :

- It shows only a part of the error information.

- The message displayed is quiet strange and can scare random innocent users.

- You are repeating few lines of code for every single query


GOOD PRATICE : (imho)

When it comes to these errors, PHP will handle that perfectly. In the configuration file (php.ini) just enable 'display_errors' (http://php.net/manual/en/errorfunc.configuration.php#ini.display-errors). This will give you full information about a potential error with a stack trace to find what cause it.

Of course for a live site you would turn display_errors off and you would have to :

    - log error.

    - inform the user with a generic error page


Again, PHP handles that perfectly with log_errors=on

And for the custom error page, let the web-server handle it (ErrorDocument for Apache and error_page for Nginx)


NB :

If you need to do more than displaying/logging , just setup a custom exception handler


Cheers,

Jonathan.

In reply to Jonathan P.

Re: How to save $DB errors to a variable

by Lloyd D -

Thanks for that Jonathan. Well the reasoning in me wanting to do this is reporting the possible errors that a student may receive during their submission to the lecturer. The lecturer can then look at the error message produced and try to resolve it. I was thinking that this would be done by saving the error message to the database then the record would be retrieved and displayed/notified to the lecturer by e-mail. I'm guessing the exceptions may be too large to store as plain text in the database? The display_errors approach would be great but as you say when the site goes live I'd have to turn it off.. how would I then log the error in this case?

In reply to Lloyd D

Re: How to save $DB errors to a variable

by Jonathan P. -

Hi,

Well i think i already gave an answer to that smile

But your reasoning is right, no matter what environment you are in (Dev or Production) Errors should be logged / displayed in a proper way. just keep in mind that the normal user doesn't need to know that clicking on this button produced a database error. He just needs to know something went wrong ! For the Developper it makes sense to have a detailed error (thats where you log everything).

Using log_errors=on (http://php.net/manual/en/errorfunc.configuration.php#ini.log-errors) should do the trick.

PHP will do everything automatically, log the error in a file, show the error page and send the appropriate HTTP response code for the Search Engine. (The PHP Manual is a gold mine wink).

In the end its your decision to save it in a file or a database. Once everything is logged, you can do whatever you want with it : sending an email with the content etc..

If you want to store everything in the database, you can ! But you will have to make your own error handler containing the right sql query.


Hope it helps,

Jonathan.

In reply to Jonathan P.

Re: How to save $DB errors to a variable

by Lloyd D -

Ok I see, I'm not sure what would be the best thing to do.. when the student submits their submission for my plugin, should I just show a generic "An error has occured" text in the feedback section of the page (under the student's submission)? Or would the better way be showing a PHP error page to the student? But then again, like you said I wouldn't want them to know what the error actually is >< 

In reply to Lloyd D

Re: How to save $DB errors to a variable

by Lloyd D -

When I said to show an "error has occurred" message to the student in the feedback section would this be a bad idea? If the process of actually displaying this message fails then the student would have no idea what's wrong...?

In reply to Lloyd D

Re: How to save $DB errors to a variable

by Jonathan P. -

Im getting confused :D

There's two types of errors :

  • Expected :
This is when you test the user input (ie. only numbers, or only an email etc..) or when a database query returns no records for example. So here you should always check for acceptable values with a bunch of if/else statements and display a message to the user (echo) 'wrong value'  , 'pls enter your nickname' etc...

  • Unexpected

This is when the database stops running or when your script needs a file that can't be located anymore for example. Basically anything unexpected :D


In your case i would treat Unexpected errors with my own error Handler. But Before that, you still need to set these directly in the php.ini file (if you can access it ) :

  1. error_reporting = E_ALL
  2. log_errors = On
  3. display_errors = Off
  4. error_log = filename   // if you want to put the logs at a specific location

If you don't have access to php.ini, just set it at the start of your script :
  1. error_reporting(E_ALL)
  2. ini_set('log_errors' , '1');
  3. ini_set('display_errors' , '0');
  4. ini_set ('error_log' , 'path/to/your/logs/errors.log');

Then you can start creating your own error handler :
  1. set_error_handler('MyGreatErrorHandler');   // set it at the top level of your application
  2. Trigger the error Handler when there's an error :
Example :
if( !mysqli_connect($servername, $user, $pass))  {
   trigger_error('Cannot Connect to Database', E_USER_ERROR);
}

     3. the function :

function MyGreatErrorHandler($code, $message, $errorLine){
    $subject = " $message - ".date();
    $body = "$errorLine"

// send an email if you want to notify the lecturer
 mail(LECTURER_EMAIL, $subject, $body);

// write everything to the log file
errror_log("$subject\r\n  $body");

// redirect the user to a generic error page  that could be displaying 'A Problem Occured - sorry for that'
header(" Location:  LINK_TO_ERROR_PAGE ");
}

This is just a quick example to help you, its not complete. In the end you could still simply solve your problem with quick and dirty try/catch blocks.

But i hope it helps.


Jonathan.


In reply to Jonathan P.

Re: How to save $DB errors to a variable

by Lloyd D -

Ah thanks so much for explaining all that, really helpful! So if one of the $DB statements (e.g $DB->update_record()) fail with an unexpected error how would I feed the error from there into my error handler? A try catch block and using the exception variable $e? Or would that no longer work with what we have now?