19

I have a php application that I have just re-factored. Unfortunately it spewing out warnings like:

Warning: preg_match() expects parameter 2 to be string, object given in /home/yacoby/dev/netbeans/php/Zend/Db/Select.php on line 776

Which is impossible (or very hard work) to work out the issue as I don't have a callstack so can't tell which parts of my code are causing the warning and there is a lot of code.

I need a method to either treat warnings like errors (In that the application dies and prints the stacktrace) or I need the stacktrace to be shown when printing errors. Is there a method to do this?

naivists
  • 32,681
  • 5
  • 61
  • 85
Yacoby
  • 54,544
  • 15
  • 116
  • 120
  • XDebug answer was accepted as it produced the best stacktrace (plus it had clickable links in my IDE ;) ). All others got +1 as well for good answers which all worked fine. – Yacoby Jan 15 '10 at 11:35
  • 1
    XDebug speaks about such a feature here http://xdebug.org/docs/stack_trace – naivists Jan 15 '10 at 11:21

3 Answers3

28

See example #1 at http://www.php.net/manual/en/class.errorexception.php

<?php
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
set_error_handler("exception_error_handler");

/* Trigger exception */
strpos();
?>
Gordon
  • 312,688
  • 75
  • 539
  • 559
Tor Valamo
  • 33,261
  • 11
  • 73
  • 81
11

Have a look at set_error_handler() and include this at the beginning of your scripts or in your bootstrap to just print the stacktrace when E_WARNINGs occur.

function stacktrace_error_handler($errno,$message,$file,$line,$context)
{
    if($errno === E_WARNING) {
        debug_print_backtrace();
    }
    return false; // to execute the regular error handler
}
set_error_handler("stacktrace_error_handler");

For more control over the various types, have a look at the more explicit version posted elsewhere in the answers.

Ariel
  • 25,995
  • 5
  • 59
  • 69
Gordon
  • 312,688
  • 75
  • 539
  • 559
  • Works, but the output uses newlines instead of
    , so it is difficult to read in HTML.
    – David Spector Aug 02 '20 at 15:06
  • Here is code for output in HTML: function GetStack() { return (new Exception())->getTraceAsString(); } // GetStack function stacktrace_error_handler($errno,$message,$file,$line,$context) { if($errno === E_WARNING) { echo nl2br(GetStack()); } return false; // to execute the regular error handler } set_error_handler("stacktrace_error_handler"); – David Spector Aug 02 '20 at 15:35
  • Here is code for output in HTML: `function GetStack() { return (new Exception())->getTraceAsString(); } // GetStack function stacktrace_error_handler($errno,$message,$file,$line,$context) { if($errno === E_WARNING) { echo nl2br(GetStack()); } return false; // to execute the regular error handler } set_error_handler("stacktrace_error_handler"); ` – David Spector Aug 02 '20 at 15:37
  • Or just wrap it in `
    ` tags and `htmlspecialchars()`. @DavidSpector.
    – TRiG Apr 01 '21 at 09:36
4

You can define your own error handler using set_error_handler()

In the handler function you can treat each class of error however you want. Here's a basic template that I use, in my case I only want to handle fatal errors, so I ignore notices and warnings.

In your case you could do a backtrace on warnings, or log them however you want

function error_handler($errno,$message,$file,$line,$context) {

switch($errno) {
    // ignore warnings and notices
    case E_WARNING:
    case E_NOTICE:
    case E_USER_NOTICE:
    case E_USER_WARNING:
        break;
    // log PHP and user errors
    case E_ERROR:
    case E_USER_ERROR:
              // Do some processing on fatal errors
    }
}
Neil Aitken
  • 7,856
  • 3
  • 41
  • 40
  • 1
    The following error types cannot be handled with a user defined function: **E_ERROR**, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called. - But I upvoted nonetheless. – Gordon Jan 15 '10 at 11:41
  • Ah, thanks for the info. I normally used this for handling USER_ERROR but wasn't aware it couldn't catch E_ERROR, although it does make sense when you think about it. – Neil Aitken Jan 15 '10 at 12:04