咳咳,各位观众,各位大佬,晚上好!我是今晚的主讲人,咱们今天要聊聊 WordPress 里一个有点意思的小家伙:_doing_it_wrong()
。
这名字听着就挺委屈的,感觉自己干了啥错事儿似的。没错,它就是专门用来“抓包”那些在开发过程中“姿势不对”的代码的。
一、_doing_it_wrong()
:名字里就写满了故事
首先,咱们看看这函数的名字:_doing_it_wrong()
。WordPress 团队的命名风格一向比较直白,这名字直接翻译过来就是“正在做错事”。
这个函数的作用也很简单粗暴:当你调用了某个被标记为“过时”、“不推荐”或者“使用方式不当”的函数、方法或代码时,它就会跳出来“提醒”你,让你知道自己犯了点小错误。
二、_doing_it_wrong()
的源码解析
咱们直接上代码,看看这小家伙到底是怎么工作的:
/**
* Fires when the theme functions are being incorrectly called.
*
* @since 3.1.0
* @since 5.5.0 Added the `$doing_it_wrong` argument.
*
* @param string $function The function that was called.
* @param string $message A message explaining what the problem is.
* @param string $version The version of WordPress where the message was added.
* @param string $doing_it_wrong Optional. Whether the _doing_it_wrong() was called. Default null.
* Pass a value to explicitly enable/disable the backtrace.
*
* @return void
*/
function _doing_it_wrong( $function, $message, $version, $doing_it_wrong = null ) {
// Allow plugins to prevent _doing_it_wrong().
if ( has_filter( 'doing_it_wrong_run' ) && ! apply_filters( 'doing_it_wrong_run', true, $function, $message, $version ) ) {
return;
}
$doing_it_wrong_trigger = true;
if ( null !== $doing_it_wrong && ! $doing_it_wrong ) {
$doing_it_wrong_trigger = false;
}
if ( WP_DEBUG && $doing_it_wrong_trigger ) {
if ( is_scalar( $message ) ) {
$message = html_entity_decode( (string) $message, ENT_QUOTES, get_option( 'html_type' ) );
}
$backtrace = wp_debug_backtrace_summary( null, 0, false );
if ( is_user_logged_in() ) {
$format = esc_html__( '%1$s was called <strong>incorrectly</strong>. %2$s. Please see <a href="%3$s" target="_blank">Debugging in WordPress</a> for more information.' ) . ' (This message was added in version %4$s.)';
$message = sprintf( $format, '<code>' . $function . '</code>', $message, 'https://wordpress.org/documentation/article/debugging-in-wordpress/', $version );
} else {
$format = esc_html__( '%1$s was called <strong>incorrectly</strong>. %2$s. Debugging in WordPress.' ) . ' (This message was added in version %4$s.)';
$message = sprintf( $format, '<code>' . $function . '</code>', $message, $version );
}
trigger_error( sprintf( '%s %s', $message, $backtrace ), E_USER_NOTICE );
}
}
咱们来一行一行地解读一下:
-
函数定义:
function _doing_it_wrong( $function, $message, $version, $doing_it_wrong = null )
$function
: 出问题(被错误使用)的函数名。$message
: 解释为什么出问题的信息。$version
: WordPress 的哪个版本开始出现这个“问题”。$doing_it_wrong
: (可选)一个布尔值,用于显式启用/禁用回溯跟踪。默认值为null
。传入一个值可以控制是否显示调用栈。
-
过滤器
doing_it_wrong_run
:if ( has_filter( 'doing_it_wrong_run' ) && ! apply_filters( 'doing_it_wrong_run', true, $function, $message, $version ) ) { return; }
WordPress 的强大之处就在于它的可扩展性。这里用了一个过滤器
doing_it_wrong_run
,允许插件阻止_doing_it_wrong()
的执行。也就是说,如果你真的知道自己在干什么,可以通过这个过滤器来“屏蔽”这些警告。 -
$doing_it_wrong
参数处理$doing_it_wrong_trigger = true; if ( null !== $doing_it_wrong && ! $doing_it_wrong ) { $doing_it_wrong_trigger = false; }
这段代码允许你通过
$doing_it_wrong
参数来控制是否触发错误。如果明确设置为false
,则不会触发错误提示。这为开发者提供了更精细的控制。 -
WP_DEBUG
检查:if ( WP_DEBUG && $doing_it_wrong_trigger ) { // ... }
这行代码很重要。
_doing_it_wrong()
只有在WP_DEBUG
为true
的时候才会真正发挥作用。WP_DEBUG
是 WordPress 的一个调试模式,开启后会显示各种错误和警告信息。 在生产环境中,一般会将WP_DEBUG
设置为false
,以避免向用户暴露敏感信息。 -
消息格式化:
if ( is_user_logged_in() ) { $format = esc_html__( '%1$s was called <strong>incorrectly</strong>. %2$s. Please see <a href="%3$s" target="_blank">Debugging in WordPress</a> for more information.' ) . ' (This message was added in version %4$s.)'; $message = sprintf( $format, '<code>' . $function . '</code>', $message, 'https://wordpress.org/documentation/article/debugging-in-wordpress/', $version ); } else { $format = esc_html__( '%1$s was called <strong>incorrectly</strong>. %2$s. Debugging in WordPress.' ) . ' (This message was added in version %4$s.)'; $message = sprintf( $format, '<code>' . $function . '</code>', $message, $version ); }
这段代码根据用户是否登录来格式化错误消息。如果用户已登录,消息会包含一个链接到 WordPress 官方文档的调试页面。
-
触发错误:
trigger_error( sprintf( '%s %s', $message, $backtrace ), E_USER_NOTICE );
这行代码才是真正“报警”的地方。
trigger_error()
函数会触发一个用户级别的错误,类型是E_USER_NOTICE
。这个错误信息会被记录到 WordPress 的错误日志中,也会在页面上显示(如果WP_DEBUG
为true
且WP_DEBUG_DISPLAY
也为true
)。
三、_doing_it_wrong()
的应用场景
_doing_it_wrong()
通常用在以下几种场景:
- 过时函数: 当某个函数被标记为过时(deprecated)时,调用它就会触发
_doing_it_wrong()
。 - 不推荐使用的函数: 有些函数虽然没有被标记为过时,但是因为存在更好的替代方案,所以不推荐使用。
- 使用方式不当: 有些函数本身没有问题,但是如果使用方式不正确,也会触发
_doing_it_wrong()
。
举个栗子:
假设 WordPress 团队觉得 my_old_function()
这个函数已经过时了,他们可能会这样标记它:
function my_old_function() {
_doing_it_wrong( 'my_old_function', 'This function is deprecated and should not be used. Use my_new_function() instead.', '5.0.0' );
// 函数的原始逻辑
}
这样,只要有人调用 my_old_function()
,就会在调试模式下看到类似这样的错误信息:
my_old_function was called incorrectly. This function is deprecated and should not be used. Use my_new_function() instead. Please see Debugging in WordPress for more information. (This message was added in version 5.0.0.)
四、_doing_it_wrong()
的意义
_doing_it_wrong()
虽然只是一个小小的函数,但是它在 WordPress 开发中却扮演着重要的角色:
- 提高代码质量: 它可以帮助开发者及时发现代码中的问题,避免使用过时或不推荐使用的函数,从而提高代码质量。
- 保持代码兼容性: 它可以提醒开发者注意 WordPress 版本的变化,避免使用在未来版本中可能被移除的函数,从而保持代码的兼容性。
- 促进代码规范: 它可以引导开发者遵循 WordPress 的代码规范,使用正确的函数和方法,从而提高代码的可读性和可维护性。
- 调试利器: 在开发过程中,开启
WP_DEBUG
后,_doing_it_wrong()
能迅速定位问题所在,大大缩短调试时间。
五、_doing_it_wrong()
和 _deprecated_function()
、_deprecated_argument()
的区别
WordPress 中还有两个类似的函数:_deprecated_function()
和 _deprecated_argument()
。它们和 _doing_it_wrong()
的区别在于:
_deprecated_function()
:专门用于标记整个函数为过时。_deprecated_argument()
:专门用于标记函数的某个参数为过时。_doing_it_wrong()
:更加通用,可以用于标记函数、参数、方法等任何代码为“使用方式不当”。
咱们用一个表格来总结一下:
函数 | 作用 | 适用对象 |
---|---|---|
_doing_it_wrong() |
标记代码使用方式不当 | 函数、参数、方法等 |
_deprecated_function() |
标记整个函数为过时 | 函数 |
_deprecated_argument() |
标记函数的某个参数为过时 | 函数的参数 |
六、如何优雅地处理 _doing_it_wrong()
警告
当你在开发过程中遇到 _doing_it_wrong()
警告时,应该怎么做呢?
- 仔细阅读警告信息: 警告信息会告诉你哪个函数被错误使用,以及为什么被错误使用。
- 查找替代方案: 根据警告信息,查找正确的替代方案。通常警告信息会告诉你应该使用哪个函数来代替。
- 更新代码: 将代码中的错误函数替换为正确的替代方案。
- 测试代码: 更新代码后,进行充分的测试,确保代码能够正常工作。
-
实在不行就屏蔽: 如果你真的有特殊原因,需要使用那些被标记为“不推荐”的函数,可以使用
doing_it_wrong_run
过滤器来屏蔽警告。但请谨慎使用这种方法,确保你真的知道自己在干什么。add_filter( 'doing_it_wrong_run', 'my_custom_doing_it_wrong_filter', 10, 4 ); function my_custom_doing_it_wrong_filter( $run, $function, $message, $version ) { // 只屏蔽特定函数的警告 if ( $function === 'my_old_function' ) { return false; // 阻止 _doing_it_wrong() 执行 } return $run; // 其他情况正常执行 }
这段代码只有在
my_old_function
被错误调用时才会阻止_doing_it_wrong()
的执行,其他情况则保持默认行为。
七、总结
_doing_it_wrong()
是 WordPress 提供的一个非常有用的调试工具,它可以帮助开发者及时发现代码中的问题,提高代码质量,保持代码兼容性。在开发过程中,如果遇到 _doing_it_wrong()
警告,一定要认真对待,及时修复代码,避免给未来的维护带来麻烦。
记住,_doing_it_wrong()
不是来找茬的,它是来帮你成为更好的 WordPress 开发者的!
好了,今天的讲座就到这里。希望大家以后在 WordPress 的开发道路上,能够尽量少地“doing it wrong”,多写出高质量的代码! 谢谢大家!