大家好!欢迎参加今天的 “WordPress 错误处理小课堂”。我是你们今天的讲师,阿伟。今天咱们不搞那些虚头巴脑的概念,直接来啃 WordPress 里的一个实用函数:_doing_it_wrong()
。
这玩意儿听起来好像在指责你,实际上,它是 WordPress 用来辅助开发者排查代码问题的利器。咱们今天就来扒一扒它的源码,看看它到底是怎么“指责”我们的,以及我们如何利用它来提高开发效率。
1. 啥是 _doing_it_wrong()
?
简单来说,_doing_it_wrong()
是 WordPress 框架提供的一个函数,用于在代码中使用了不推荐的方法、过时的函数或者出现了潜在问题时,触发一个 E_USER_NOTICE
级别的错误。这个错误不会中断程序的运行,但会在调试模式下显示出来,提醒你:“嘿,哥们儿,你这么写不太对劲啊!”
2. 源码剖析:_doing_it_wrong()
的庐山真面目
让我们先来看一下 _doing_it_wrong()
的源码 (基于 WordPress 6.4.2):
/**
* Marks a function, method, or class as deprecated and triggers a user error when accessed.
*
* Use of already deprecated functions, methods, or classes should trigger
* a user error to help developers identify them during code audits.
*
* @since 2.3.0
* @since 4.5.0 The `$message` argument supports้านstring interpolation.
*
* @param string $function The function that was called.
* @param string $version The version of WordPress that deprecated the function.
* @param string $message Optional. A message regarding the change.
* Default null.
*/
function _doing_it_wrong( $function, $version, $message = null ) {
$backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 );
$bt_file = isset( $backtrace[0]['file'] ) ? wp_basename( $backtrace[0]['file'] ) : '';
$bt_line = isset( $backtrace[0]['line'] ) ? $backtrace[0]['line'] : '';
$message = sprintf(
/* translators: 1: PHP function name, 2: WordPress version number. */
__( '%1$s was called incorrectly.' ),
$function
);
if ( ! is_null( $message ) ) {
$message .= ' ' . sprintf( __( '%s.' ), $message );
}
/* translators: 1: File name, 2: Line number. */
$message .= ' ' . sprintf( __( 'Please see <a href="%s">Debugging in WordPress</a> for more information.' ), 'https://wordpress.org/documentation/article/debugging-in-wordpress/' );
$message .= " (This message was added in version $version.)";
if ( WP_DEBUG && apply_filters( 'doing_it_wrong_trigger_error', true ) ) {
trigger_error( sprintf( '%s in %s on line %s', $message, $bt_file, $bt_line ), E_USER_NOTICE );
}
do_action( 'doing_it_wrong_run', $function, $message, $version, $bt_file, $bt_line );
}
让我们一行一行地解读:
-
function _doing_it_wrong( $function, $version, $message = null )
: 定义函数,接收三个参数:$function
: 出错的函数/方法/类的名字。$version
: 从哪个 WordPress 版本开始不推荐使用。$message
: 可选的错误信息,用于更详细地说明问题。
-
$backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 );
: 获取函数调用堆栈信息。debug_backtrace()
是一个 PHP 函数,可以获取当前脚本的调用堆栈。DEBUG_BACKTRACE_IGNORE_ARGS
参数表示我们不需要函数参数的信息,而2
表示我们只需要获取调用堆栈中的两层信息(当前函数和调用它的函数)。这个信息主要用来确定出错的文件和行号。 -
$bt_file = isset( $backtrace[0]['file'] ) ? wp_basename( $backtrace[0]['file'] ) : '';
: 从调用堆栈信息中提取文件名。wp_basename()
函数用于获取文件名,不包含路径。 -
$bt_line = isset( $backtrace[0]['line'] ) ? $backtrace[0]['line'] : '';
: 从调用堆栈信息中提取行号。 -
$message = sprintf( /* translators: 1: PHP function name, 2: WordPress version number. */ __( '%1$s was called incorrectly.' ), $function );
: 构建错误信息。sprintf()
函数用于格式化字符串。__( '%1$s was called incorrectly.' )
是一个本地化函数,用于翻译错误信息。%1$s
会被$function
的值替换。 -
if ( ! is_null( $message ) ) { $message .= ' ' . sprintf( __( '%s.' ), $message ); }
: 如果提供了额外的错误信息,则将其添加到错误信息中。 -
$message .= ' ' . sprintf( __( 'Please see <a href="%s">Debugging in WordPress</a> for more information.' ), 'https://wordpress.org/documentation/article/debugging-in-wordpress/' );
: 添加一个指向 WordPress 调试文档的链接,方便开发者查找更多信息。 -
$message .= " (This message was added in version $version.)";
: 添加错误信息添加的版本号。 -
if ( WP_DEBUG && apply_filters( 'doing_it_wrong_trigger_error', true ) ) { trigger_error( sprintf( '%s in %s on line %s', $message, $bt_file, $bt_line ), E_USER_NOTICE ); }
: 这是最关键的一步。 如果WP_DEBUG
常量为true
(表示开启了调试模式),并且apply_filters( 'doing_it_wrong_trigger_error', true )
返回true
(允许触发错误),则使用trigger_error()
函数触发一个E_USER_NOTICE
级别的错误。WP_DEBUG
: WordPress 的调试模式开关。 通常在wp-config.php
文件中定义。apply_filters( 'doing_it_wrong_trigger_error', true )
: 允许通过 filter 来控制是否触发错误。 默认情况下,会触发错误。trigger_error( sprintf( '%s in %s on line %s', $message, $bt_file, $bt_line ), E_USER_NOTICE );
: PHP 的内置函数,用于触发一个用户级别的错误。E_USER_NOTICE
表示这是一个通知级别的错误,不会中断程序运行。
-
do_action( 'doing_it_wrong_run', $function, $message, $version, $bt_file, $bt_line );
: 触发一个 action hook,允许其他插件或主题监听并执行一些操作。例如,可以记录错误日志或者发送通知。
3. trigger_error()
:错误报告的幕后英雄
_doing_it_wrong()
的核心在于使用了 PHP 的 trigger_error()
函数。 trigger_error()
允许开发者手动触发一个错误。 它的语法如下:
trigger_error ( string $error_msg [, int $error_type = E_USER_NOTICE ] ) : bool
$error_msg
: 错误信息。-
$error_type
: 错误类型。 可以是以下常量之一:常量 描述 E_USER_ERROR
用户产生的错误信息。 程序会终止运行。 E_USER_WARNING
用户产生的警告信息。 程序会继续运行。 E_USER_NOTICE
用户产生的提示信息。 程序会继续运行。 _doing_it_wrong()
默认使用这个级别。E_USER_DEPRECATED
用户产生的提示信息,表明代码已过时。 这个级别从 PHP 5.3.0 开始可用。
trigger_error()
的返回值是一个布尔值,表示是否成功触发错误。 如果错误处理机制被禁用,或者提供的 $error_type
无效,则返回 false
。
4. 如何利用 _doing_it_wrong()
辅助开发?
_doing_it_wrong()
并不是 WordPress 框架的专利。 你完全可以在自己的插件或主题中使用它,来帮助你:
-
标记过时的函数或方法: 当你想废弃一个函数或方法时,可以使用
_doing_it_wrong()
来提醒开发者不要再使用它。 -
提示潜在的问题: 如果你的代码中存在一些潜在的问题,但又不想直接抛出异常,可以使用
_doing_it_wrong()
来提示开发者。 -
强制执行最佳实践: 如果你想强制开发者遵循某些最佳实践,可以使用
_doing_it_wrong()
来提醒他们。
5. 实战演练:在插件中使用 _doing_it_wrong()
假设你正在开发一个插件,其中有一个函数 my_plugin_old_function()
已经过时了,你想提醒开发者不要再使用它。 你可以这样做:
/**
* @deprecated 1.0.0 Use my_plugin_new_function() instead.
*/
function my_plugin_old_function() {
_doing_it_wrong(
'my_plugin_old_function',
'1.0.0',
'Use my_plugin_new_function() instead.'
);
// 旧函数的逻辑
echo 'This function is deprecated. Please use my_plugin_new_function() instead.';
}
function my_plugin_new_function() {
// 新函数的逻辑
echo 'This is the new function.';
}
// 调用旧函数
my_plugin_old_function();
在这个例子中,当 my_plugin_old_function()
被调用时,_doing_it_wrong()
函数会被执行,从而触发一个 E_USER_NOTICE
级别的错误。
注意:你需要开启 WordPress 的调试模式 (WP_DEBUG = true) 才能看到这个错误信息。
6. 进阶技巧:使用 filter 禁用 _doing_it_wrong()
的错误提示
有时候,你可能不想在某些情况下显示 _doing_it_wrong()
的错误提示。 例如,你可能只想在开发环境中显示错误提示,而在生产环境中禁用它。 你可以使用 doing_it_wrong_trigger_error
filter 来实现这一点。
add_filter( 'doing_it_wrong_trigger_error', 'my_plugin_disable_doing_it_wrong_error', 10, 1 );
function my_plugin_disable_doing_it_wrong_error( $trigger_error ) {
if ( defined( 'WP_ENVIRONMENT_TYPE' ) && WP_ENVIRONMENT_TYPE === 'production' ) {
return false; // 在生产环境中禁用错误提示
}
return $trigger_error; // 其他环境保持默认行为
}
在这个例子中,我们定义了一个 filter 函数 my_plugin_disable_doing_it_wrong_error()
,它会检查当前环境是否为生产环境。 如果是生产环境,则返回 false
,从而禁用 _doing_it_wrong()
的错误提示。
7. _deprecated_function()
和 _deprecated_argument()
:两位好兄弟
WordPress 还有两个与 _doing_it_wrong()
类似的函数:_deprecated_function()
和 _deprecated_argument()
。
-
_deprecated_function( string $function, string $version, string $replacement = null )
: 用于标记一个函数已经过时。 与_doing_it_wrong()
类似,但更专注于标记过时函数。 它会触发一个E_USER_DEPRECATED
级别的错误。 -
_deprecated_argument( string $function, string $version, string $message = null )
: 用于标记一个函数的参数已经过时。 如果函数使用了过时的参数,它会触发一个E_USER_DEPRECATED
级别的错误。
这三个函数可以帮助你更好地管理你的代码,并确保开发者使用正确的方法。
8. 总结:拥抱错误,拥抱进步
_doing_it_wrong()
并不是一个让人害怕的函数。 相反,它是一个帮助你提高代码质量的工具。 通过合理地使用 _doing_it_wrong()
和 trigger_error()
,你可以更早地发现代码中的问题,并及时修复它们。
记住,错误是进步的阶梯。 拥抱错误,拥抱进步,让我们的代码更加健壮!
表格总结
函数/常量/Filter | 描述 |
---|---|
_doing_it_wrong() |
用于标记代码使用了不推荐的方法、过时的函数或者出现了潜在问题时,触发一个 E_USER_NOTICE 级别的错误。 |
trigger_error() |
PHP 内置函数,用于触发一个用户级别的错误。 |
E_USER_NOTICE |
trigger_error() 函数可以使用的错误类型,表示用户产生的提示信息。程序会继续运行。 |
WP_DEBUG |
WordPress 的调试模式开关。通常在 wp-config.php 文件中定义。 |
doing_it_wrong_trigger_error |
filter,用于控制是否触发 _doing_it_wrong() 的错误提示。 |
_deprecated_function() |
用于标记一个函数已经过时。与 _doing_it_wrong() 类似,但更专注于标记过时函数。 它会触发一个 E_USER_DEPRECATED 级别的错误。 |
_deprecated_argument() |
用于标记一个函数的参数已经过时。如果函数使用了过时的参数,它会触发一个 E_USER_DEPRECATED 级别的错误。 |
好了,今天的课程就到这里。 希望大家能有所收获,并在实际开发中灵活运用 _doing_it_wrong()
。 下次再见!