W
W
wartur2011-12-14 22:25:13
PHP
wartur, 2011-12-14 22:25:13

Xdebug - tell me with a solution to the issue of displaying errors (xdebug_start_error_collection)

Hello PHP-habrapublic.

Again I start to disturb you because of the decision of thin questions of the correct programming.
This raises another interesting question for inquisitive PHP minds.

Introduction:


There is Xdebug - this is a sacred thing, it has good functionality, one of which is displaying errors in a beautiful way, which we will talk about. On the subject of error trapping , I found 3 great functions:
  • xdebug_start_error_collection - starts saving all code problems somewhere in its buffer in a beautiful form, thereby preserving a beautiful view, and error output seems to be turned off.
  • xdebug_get_collected_errors - Displays data collected so far. Accordingly, you can display errors in the right place
  • xdebug_stop_error_collection - the order to stop accumulating data, in principle, you can not even call it, but just inserted it here for completeness.


Moving on to the question


Friends, they don’t work like a couple , I have already dug up all the documentation, read all the configs, and they are not mentioned at all on other resources, since they rarely use it, but I see that it’s really cool to use it, since everything works “out of the box” and you don’t have to intercept all this yourself (set_error_handler, for example) and spend hours on a beautifully displayed programmer.
I have xampp assembly 1.7.4, they don’t swear at functions, so xdebug version >= 2.1, they don’t work stupidly. Well, they do not buffer and that's it, as if they were not called at all.

UPD: I give examples
echo "before xdebug_start_error_collection\n";
xdebug_start_error_collection();
echo "after xdebug_start_error_collection\n";
echo $generate_notice; // переменная ранее не была объявлена, значит будет E_NOTICE
echo "after notice generate\n";
xdebug_get_collected_errors();
echo "after xdebug_get_collected_errors";


before xdebug_start_error_collection
after xdebug_start_error_collection
// There's a lot of xdebug data here
after notice generate
// nothing here, in fact the output should have "delayed" until this point
after xdebug_get_collected_errors

Reason for use:


Conditions and Task

There is some code in which something is output to the stream. On the working server, of course, they will not be displayed at all (error output is disabled), but on the local server I wanted to display this output in the “standard xdebug beautiful ways” to the right place in the browser (for me, this is at the very top before the html tag, and not where anything inside the title tag).

I note one more condition:
Everything is output via echo, that is, no buffered output is used through accumulation into a string variable (I recently excluded this from my system for its slowness - up to 30% worsens the speed when calling the ".=" operator in bulk) . The ob_*** buffering functions do not work, because no matter what stack you write to, errors still end up in the standard output, or I haven’t figured out a way to do it.

Decision

Here is the solution for you - these are just these 3 functions. And I'll save the echo, and I'll display the errors in the right place, and they will also be beautifully designed with profiling and a kolstek.

What if we can't brainstorm the answer?


I will disturb the developers, I don't want to disturb them and ask stupid questions if they are really stupid. If I have to write, then I will write an article about this later, so that everyone knows that there are such goodies in our lives.

Please help who can or who came across by accident.
Thank you.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
W
wartur, 2011-12-15
@wartur

Gentlemen, it's a bug. As you can see from the code, the function does not fulfill its purpose, even the basic one - “hiding error data”, I can’t say anything about accumulation.

/* Display errors */
if (PG(display_errors) && !PG(during_request_startup)) {
  char *printable_stack;

  /* We need to see if we have an uncaught exception fatal error now */
  if (type == E_ERROR && strncmp(buffer, "Uncaught exception", 18) == 0) {
    xdebug_str str = {0, 0, NULL};
    char *tmp_buf, *p;
        
    /* find first new line */
    p = strchr(buffer, '\n');
    /* find last quote */
    p = ((char *) zend_memrchr(buffer, '\'', p - buffer)) + 1;
    /* Create new buffer */
    tmp_buf = calloc(p - buffer + 1, 1);
    strncpy(tmp_buf, buffer, p - buffer );

    /* Append error */
    xdebug_append_error_head(&str, PG(html_errors) TSRMLS_CC);
    xdebug_append_error_description(&str, PG(html_errors), error_type_str, tmp_buf, error_filename, error_lineno TSRMLS_CC);
    xdebug_append_printable_stack(&str, PG(html_errors) TSRMLS_CC);
    xdebug_str_add(&str, XG(last_exception_trace), 0);
    xdebug_append_error_footer(&str, PG(html_errors));
    php_output_error(str.d TSRMLS_CC);

    xdfree(str.d);
    free(tmp_buf);
  } else {
    printable_stack = get_printable_stack(PG(html_errors), error_type_str, buffer, error_filename, error_lineno TSRMLS_CC);
    php_output_error(printable_stack TSRMLS_CC);
    xdfree(printable_stack);
  }
}
if (XG(do_collect_errors)) {
  char *printable_stack;
  printable_stack = get_printable_stack(PG(html_errors), error_type_str, buffer, error_filename, error_lineno TSRMLS_CC);
  xdebug_llist_insert_next(XG(collected_errors), XDEBUG_LLIST_TAIL(XG(collected_errors)), printable_stack);
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question