_doing_it_wrong()WP 3.1.0

Отметить что-либо, как "сделано неправильно". Например, функция вызвана неправильно, параметр указан неправильно и т.д.

Сообщение будет показано только если включен режим дебага - WP_DEBUG = true.

Функция вызывает хук doing_it_wrong_run, который можно использовать в своих целях для обработки ошибки. Например этот хук пригодится для рабочего сайта где отключен режим дебага, но мы хотим ловить ошибки "сделано неправильно". Для этого, вешаем на этот хук свою функцию и обрабатываем полученные ошибки, например, сохраняем их в файл или отправляем себе email об ошибке.

Функция работает на основе PHP функции trigger_error().

Внутренняя функция — эта функция рассчитана на использование самим ядром. Не рекомендуется использовать эту функцию в своем коде.

Хуки из функции

Возвращает

null. Ничего.

Использование

_doing_it_wrong( $function, $message, $version );
$function(строка) (обязательный)
Название функции в которой что-либо делается неправильно.
$message(строка) (обязательный)
Сообщение, объясняющее, что было сделано неправильно.
$version(строка) (обязательный)
Версия WordPress, с которой это действие стало неправильным (устарелым).

Примеры

1

#1 Покажем ошибку, когда функция вызвана не на том хуке.

Этот пример из ядра ВП. В нем пользователю сообщается что он вызвал функцию регистрации REST маршрута не на хуке rest_api_init, как это должно быть сделано. См. код register_rest_route().

    if ( ! did_action( 'rest_api_init' ) ) {
		_doing_it_wrong(
			'register_rest_route',
			sprintf(
				/* translators: %s: rest_api_init */
				__( 'REST API routes must be registered on the %s action.' ),
				'<code>rest_api_init</code>'
			),
			'5.1.0'
		);
	}
0

#2 Покажем ошибку, когда в функции нет глобальной переменной с которой она работает

В этом примере для работы функции is_archive() нужна глобальная переменная $wp_query, это значит что функцию нужно вызывать после того как эта переменная определена. Если она вызывается раньше, выведем ошибку об этом.

function is_archive() {
	global $wp_query;

	if ( ! isset( $wp_query ) ) {
		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1.0' );
		return false;
	}

	return $wp_query->is_archive();
}
0

#3 Найдем из какого места в коде была вызвана функция _doing_it_wrong()

К сожалению, по логам (см. Отладка в Wordpress) от _doing_it_wrong() не ясно, в каком месте была сгенерирована ошибка, например:

[05-Dec-2022 15:34:53 UTC] PHP Notice:  Функция WP_Scripts::localize вызвана неправильно.
Параметр $l10n должен быть массивом. Для передачи произвольных данных в скрипты используйте
функцию wp_add_inline_script(). Дополнительную информацию можно найти на странице
<a href="https://ru.wordpress.org/support/article/debugging-in-wordpress/">Отладка в WordPress</a>.
(Это сообщение было добавлено в версии 5.7.0.) in F:\server\www\site.edit\wp-includes\functions.php on line 5835

Логирование (дебаг) этой ошибки на первый взгляд непростая задача, потому что по самой ошибке непонятно, что её вызвало.

Чтобы найти место в коде, где появилась ошибка doing_it_wrong, можно использовать такой код:

add_filter( 'doing_it_wrong_trigger_error', 'doing_it_wrong__add_debug_backtrace' );

/**
 * Логирует ошибки от _doing_it_wrong().
 *
 * @param bool $trigger
 *
 * @return bool mixed
 */
function doing_it_wrong__add_debug_backtrace( $trigger ) {
	if ( true === $trigger ) {
		error_log(
			print_r( wp_debug_backtrace_summary( null, null, false ), true )
		);
	}

	return $trigger;
}

Теперь, кроме описания ошибки в логах, мы также увидим весь стек вызовов, который привел к этой ошибке:

[05-Dec-2022 15:34:53 UTC] Array
(
	[0] => doing_it_wrong_trigger_error_logger
	[1] => WP_Hook->apply_filters
	[2] => apply_filters('doing_it_wrong_trigger_error')
	[3] => _doing_it_wrong
	[4] => WP_Scripts->localize
	[5] => wp_localize_script
	[6] => WPML_ST_Theme_Plugin_Localization_Resources->enqueue_scripts
	[7] => WP_Hook->apply_filters
	[8] => WP_Hook->do_action
	[9] => do_action('admin_enqueue_scripts')
	[10] => require_once('wp-admin/admin-header.php')
)

[05-Dec-2022 15:34:53 UTC] PHP Notice:  Функция WP_Scripts::localize вызвана неправильно.
Параметр $l10n должен быть массивом. Для передачи произвольных данных в скрипты используйте
функцию wp_add_inline_script(). Дополнительную информацию можно найти на странице
<a href="https://ru.wordpress.org/support/article/debugging-in-wordpress/">«Отладка в WordPress»</a>.
(Это сообщение было добавлено в версии 5.7.0.) in F:\server\www\site.edit\wp-includes\functions.php on line 5835

Сразу видно в каком классе и его методе что-то не так. С помощью не долгих поисков находим проблемный участок кода:

// ...

wp_enqueue_style(
	'wpml-theme-plugin-localization-scan',
	WPML_ST_URL . '/res/css/theme-plugin-localization/theme-plugin-localization.css',
	array(),
	WPML_ST_VERSION
);

wp_localize_script(
	'wpml-theme-plugin-localization-scan',
	'wpml_groups_to_scan',
	get_option( WPML_ST_Themes_And_Plugins_Updates::WPML_ST_ITEMS_TO_SCAN )
);

wp_enqueue_script(
	'wpml-st-tracking-all-strings-as-english-notice',
	WPML_ST_URL . '/res/js/tracking-all-strings-as-english-notice.js',
	array( 'jquery' ),
	WPML_ST_VERSION
);

// ...

Он находится в файле:

wp-content/plugins/wpml-string-translation/classes/menus/theme-plugin-localization-ui/class-wpml-st-theme-plugin-localization-resources.php

Вы можете скофигурировать wp_debug_backtrace_summary() как-то по-своему. Или можно использовать функции трассировки PHP: debug_print_backtrace() или debug_backtrace().

Можно также добавить дополнительную логику, чтобы не показывать подобную трассировку при каких-либо условиях. Например, не будем генерировать такое в некоторых функциях (методах):

add_filter( 'doing_it_wrong_trigger_error', 'doing_it_wrong__add_debug_backtrace' );

/**
 * Логирует ошибки от _doing_it_wrong().
 *
 * @param bool $trigger
 *
 * @return bool
 */
function doing_it_wrong__add_debug_backtrace( $trigger ) {
	if ( $trigger ) {
		$excludes  = [ 'WPML_ST_Theme_Plugin_Localization_Resources->enqueue_scripts', 'some_other_function' ];
		$backtrace = wp_debug_backtrace_summary( null, null, false );
		$hide      = array_intersect( $excludes, $backtrace );

		if ( $hide ) {
			$trigger = false;
		} else {
			error_log( print_r( $backtrace, true ) );
		}
	}

	return $trigger;
}

Список изменений

С версии 3.1.0 Введена.
С версии 5.4.0 This function is no longer marked as "private".

Код _doing_it_wrong() WP 6.5.2

function _doing_it_wrong( $function_name, $message, $version ) {

	/**
	 * Fires when the given function is being used incorrectly.
	 *
	 * @since 3.1.0
	 *
	 * @param string $function_name The function that was called.
	 * @param string $message       A message explaining what has been done incorrectly.
	 * @param string $version       The version of WordPress where the message was added.
	 */
	do_action( 'doing_it_wrong_run', $function_name, $message, $version );

	/**
	 * Filters whether to trigger an error for _doing_it_wrong() calls.
	 *
	 * @since 3.1.0
	 * @since 5.1.0 Added the $function_name, $message and $version parameters.
	 *
	 * @param bool   $trigger       Whether to trigger the error for _doing_it_wrong() calls. Default true.
	 * @param string $function_name The function that was called.
	 * @param string $message       A message explaining what has been done incorrectly.
	 * @param string $version       The version of WordPress where the message was added.
	 */
	if ( WP_DEBUG && apply_filters( 'doing_it_wrong_trigger_error', true, $function_name, $message, $version ) ) {
		if ( function_exists( '__' ) ) {
			if ( $version ) {
				/* translators: %s: Version number. */
				$version = sprintf( __( '(This message was added in version %s.)' ), $version );
			}

			$message .= ' ' . sprintf(
				/* translators: %s: Documentation URL. */
				__( 'Please see <a href="%s">Debugging in WordPress</a> for more information.' ),
				__( 'https://wordpress.org/documentation/article/debugging-in-wordpress/' )
			);

			$message = sprintf(
				/* translators: Developer debugging message. 1: PHP function name, 2: Explanatory message, 3: WordPress version number. */
				__( 'Function %1$s was called <strong>incorrectly</strong>. %2$s %3$s' ),
				$function_name,
				$message,
				$version
			);
		} else {
			if ( $version ) {
				$version = sprintf( '(This message was added in version %s.)', $version );
			}

			$message .= sprintf(
				' Please see <a href="%s">Debugging in WordPress</a> for more information.',
				'https://wordpress.org/documentation/article/debugging-in-wordpress/'
			);

			$message = sprintf(
				'Function %1$s was called <strong>incorrectly</strong>. %2$s %3$s',
				$function_name,
				$message,
				$version
			);
		}

		wp_trigger_error( '', $message );
	}
}