wp_debug_backtrace_summary()WP 3.4.0

Return a comma-separated string of functions that have been called to get to the current point in code.

1 time — 0.000001 sec (speed of light) | 50000 times — 0.23 sec (very fast) | PHP 7.1.11, WP 4.9.8

No Hooks.

Return

String|Array. Either a string containing a reversed comma separated trace or an array of individual calls.

Usage

wp_debug_backtrace_summary( $ignore_class, $skip_frames, $pretty );
$ignore_class(string)
A class to ignore all function calls within - useful when you want to just give info about the callee.
Default: null
$skip_frames(int)
A number of stack frames to skip - useful for unwinding back to the source of the issue.
$pretty(true|false)
Whether you want a comma separated string instead of the raw array returned.
Default: true

Examples

0

#1 Demo of what the function outputs

For example, connect to the hook pre_get_posts and see what wp_debug_backtrace_summary() returns with different parameters:

add_filter( 'pre_get_posts', 'my_function' );

function my_function(){

	$backtrace = wp_debug_backtrace_summary();
	/*
	require('/sites/test.ru/wp-blog-header.php'), wp, WP->main, WP->query_posts, WP_Query->query,
	WP_Query->get_posts, do_action_ref_array, WP_Hook->do_action, WP_Hook->apply_filters, my_function
	*/

	// Remove methods of the 'WP_Hook' class
	$backtrace = wp_debug_backtrace_summary( 'WP_Hook' );
	/*
	require('/sites/test.ru/wp-blog-header.php'), wp, WP->main, WP->query_posts, WP_Query->query,
	WP_Query->get_posts, do_action_ref_array, my_function
	*/

	// Remove the last 5 elements
	// The parameter `$ignore_class` is not taken into account when counting items, 
	// i.e. items are counted as if `$ignore_class=null`.
	$backtrace = wp_debug_backtrace_summary( 'WP_Hook', 5 );
	//>  require('/sites/test.ru/wp-blog-header.php'), wp, WP->main, WP->query_posts, WP_Query->query

	// get an array
	$backtrace = wp_debug_backtrace_summary( 'WP_Hook', 5, false );
	/*
	Array(
		[0] => WP_Query->query
		[1] => WP->query_posts
		[2] => WP->main
		[3] => wp
		[4] => require('/sites/test.ru/wp-blog-header.php')
	)
	*/

}
0

#2 Changing the time format in the "Recent Posts" widget

Unfortunately, there are no special hooks in the Recent Posts widget to change the date and time display format, but we can use the following trick:

add_filter( 'pre_option_date_format', function ( $pre_option ) {

	$backtrace = wp_debug_backtrace_summary( null, 0, false );

	if ( in_array( 'WP_Widget_Recent_Posts->widget', $backtrace ) ) {
		return 'G:i';
	}

	return $pre_option;
} );
0

#3 Add a call chain to the log

Suppose we need to add an error message to our logger. In this case it would be convenient to have a stack of calls to functions/methods that caused the error along with the error message:

function some_function(){

	// some code where an error might appear

	if( is_wp_error() ){
		$logger->error( 'Error message.', [ 'backtrace' => wp_debug_backtrace_summary() ] );
		return;
	}

	// do staff

}

Notes

Changelog

Since 3.4.0 Introduced.

wp_debug_backtrace_summary() code WP 6.7.1

function wp_debug_backtrace_summary( $ignore_class = null, $skip_frames = 0, $pretty = true ) {
	static $truncate_paths;

	$trace       = debug_backtrace( false );
	$caller      = array();
	$check_class = ! is_null( $ignore_class );
	++$skip_frames; // Skip this function.

	if ( ! isset( $truncate_paths ) ) {
		$truncate_paths = array(
			wp_normalize_path( WP_CONTENT_DIR ),
			wp_normalize_path( ABSPATH ),
		);
	}

	foreach ( $trace as $call ) {
		if ( $skip_frames > 0 ) {
			--$skip_frames;
		} elseif ( isset( $call['class'] ) ) {
			if ( $check_class && $ignore_class === $call['class'] ) {
				continue; // Filter out calls.
			}

			$caller[] = "{$call['class']}{$call['type']}{$call['function']}";
		} else {
			if ( in_array( $call['function'], array( 'do_action', 'apply_filters', 'do_action_ref_array', 'apply_filters_ref_array' ), true ) ) {
				$caller[] = "{$call['function']}('{$call['args'][0]}')";
			} elseif ( in_array( $call['function'], array( 'include', 'include_once', 'require', 'require_once' ), true ) ) {
				$filename = isset( $call['args'][0] ) ? $call['args'][0] : '';
				$caller[] = $call['function'] . "('" . str_replace( $truncate_paths, '', wp_normalize_path( $filename ) ) . "')";
			} else {
				$caller[] = $call['function'];
			}
		}
	}
	if ( $pretty ) {
		return implode( ', ', array_reverse( $caller ) );
	} else {
		return $caller;
	}
}