深入理解 WordPress `_doing_it_wrong()` 函数的源码:它如何在开发过程中提供有用的性能建议。

各位听众,晚上好!我是今天的讲师,咱们今天聊聊WordPress里那个让人又爱又恨的 _doing_it_wrong() 函数。别看它名字这么滑稽,实际上它可是个开发过程中的“贴心老妈”,总是在你犯错的时候唠叨几句,帮你避免掉进坑里。

_doing_it_wrong():名字风趣,职责严肃

首先,咱们得明白 _doing_it_wrong() 函数是干嘛的。简单来说,它是一个用于标记代码中使用了被废弃的函数、参数或者不推荐的使用方式的函数。它的主要目的是:

  • 提醒开发者: 使用了不规范或者过时的代码,以便及时更新。
  • 提供上下文信息: 告诉你哪里出了问题,以及建议的替代方案。
  • 促进代码质量: 鼓励开发者遵循最佳实践,编写更健壮、更易维护的代码。

源码剖析:这老妈子是怎么唠叨的?

咱们直接上源码,看看这“老妈子”到底是怎么工作的。在 WordPress 核心代码里, _doing_it_wrong() 函数通常定义在 wp-includes/functions.php 文件中。 简化后的代码可能是这样的:

/**
 * Fires when a function is doing something that should have triggered
 * a deprecated notice.
 *
 * @since 3.1.0
 *
 * @param string $function  The function that was called.
 * @param string $message   A message explaining what the function is
 *                          doing that is wrong.
 * @param string $version   The version of WordPress that the feature became
 *                          deprecated.
 *
 * @return void
 */
function _doing_it_wrong( $function, $message, $version ) {
    if ( did_action( 'doing_it_wrong_run' ) ) {
        /**
         * Fires after a function is doing something that should have triggered
         * a deprecated notice.
         *
         * @since 3.1.0
         *
         * @param string $function The function that was called.
         * @param string $message  A message explaining what the function is
         *                         doing that is wrong.
         * @param string $version  The version of WordPress that the feature became
         *                         deprecated.
         */
        do_action( 'doing_it_wrong_run', $function, $message, $version );
    } else {
        $doing_it_wrong = Doing_It_Wrong::instance();
        $doing_it_wrong->doing_it_wrong( $function, $message, $version );
    }
}

class Doing_It_Wrong {

    /**
     * The singleton instance.
     *
     * @since 6.4.0
     *
     * @var Doing_It_Wrong
     */
    private static $instance;

    /**
     * Gets the instance of this class.
     *
     * @since 6.4.0
     *
     * @return Doing_It_Wrong
     */
    public static function instance() {
        if ( ! isset( self::$instance ) ) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     * Handles calling _doing_it_wrong properly.
     *
     * @since 6.4.0
     *
     * @param string $function  The function that was called.
     * @param string $message   A message explaining what the function is doing that is wrong.
     * @param string $version   The version of WordPress that the feature became deprecated.
     */
    public function doing_it_wrong( $function, $message, $version ) {
        if ( WP_DEBUG && apply_filters( 'doing_it_wrong_trigger_error', true ) ) {
            $message = sprintf( '%1$s 被错误地调用。%2$s 自版本 %3$s 起可用。', $function, $message, $version );

            if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
                header( 'X-WP-Doing-It-Wrong: ' . wp_strip_all_tags( $message ) );
            }

            trigger_error( esc_html( $message ), E_USER_NOTICE );
        }
    }
}

咱们来解读一下:

  1. 参数:

    • $function:出错的函数名。
    • $message:错误信息,告诉你错在哪儿了。
    • $version:从哪个 WordPress 版本开始这个函数/用法被标记为不推荐。
  2. WP_DEBUG 判断: 只有当 WP_DEBUG 常量被设置为 true 时,这个函数才会真正“唠叨”你。这是为了避免在生产环境中给用户看到错误信息。WP_DEBUG 默认是 false,所以你需要在 wp-config.php 文件中把它设置为 true 才能看到效果。

  3. apply_filters( 'doing_it_wrong_trigger_error', true ): 允许通过过滤器禁用错误触发。 默认情况下,会触发错误。

  4. 错误信息格式化: 函数会把传入的参数格式化成一条友好的错误信息,告诉你哪个函数用错了,错在哪里,以及从哪个版本开始不推荐使用。

  5. trigger_error(): 这是关键的一步。它会触发一个 E_USER_NOTICE 级别的错误。这意味着这个错误不会中断程序的执行,但会在错误日志中记录下来,或者在开启了 WP_DEBUG 并且配置了 WP_DEBUG_LOG 的情况下,写入到 wp-content/debug.log 文件中。

  6. AJAX 请求特殊处理: 如果是 AJAX 请求,错误信息会被添加到 X-WP-Doing-It-Wrong HTTP 响应头中。这样,前端 JavaScript 代码就可以捕获这个信息,并进行相应的处理(比如显示警告信息)。

举个栗子:get_currentuserinfo() 的遭遇

get_currentuserinfo() 函数曾经是 WordPress 中获取当前用户信息的老牌函数。但是,它已经被废弃了,取而代之的是更好的 wp_get_current_user() 函数。

如果在你的代码中使用了 get_currentuserinfo(),WordPress 就会调用 _doing_it_wrong() 函数来提醒你:

if ( ! function_exists( 'get_currentuserinfo' ) ) {
    /**
     * Retrieve information about the current user.
     *
     * @since 2.0.0
     * @deprecated 4.5.0 Use wp_get_current_user()
     *
     * @global WP_User $current_user
     *
     * @param int $deprecated Not used.
     * @return WP_User|null WP_User object on success, null for failure.
     */
    function get_currentuserinfo( $deprecated = '' ) {
        _doing_it_wrong( __FUNCTION__, '使用 wp_get_current_user() 替代。', '4.5.0' );

        if ( ! is_numeric( $deprecated ) ) {
            $deprecated = '';
        }

        wp_get_current_user();
    }
}

这段代码的意思是:

  • 如果 get_currentuserinfo() 函数不存在(通常是第一次运行的时候),就定义一个。
  • 在这个函数内部,调用 _doing_it_wrong(),告诉开发者:
    • 你用错了函数 (__FUNCTION__ 会自动替换为函数名 get_currentuserinfo)。
    • 你应该使用 wp_get_current_user() 替代。
    • 这个函数从 4.5.0 版本开始被标记为不推荐使用。
  • 最后,为了兼容性,它还会调用 wp_get_current_user(),保证代码还能正常工作。

如果你开启了 WP_DEBUG,并在代码中调用了 get_currentuserinfo(),你会在 WordPress 后台看到类似这样的警告信息:

get_currentuserinfo 被错误地调用。使用 wp_get_current_user() 替代。自版本 4.5.0 起可用。

或者,如果你配置了 WP_DEBUG_LOG,你会在 wp-content/debug.log 文件中看到同样的错误信息。

_doing_it_wrong() 的价值:不仅仅是警告

_doing_it_wrong() 的价值远不止于发出警告。它还具有以下重要意义:

  • 长期兼容性: WordPress 核心团队会尽量保持向后兼容性,但有些过时的函数/用法最终会被移除。_doing_it_wrong() 提醒你尽早更新代码,避免将来出现问题。
  • 性能优化: 有些被废弃的函数/用法可能效率较低,或者存在安全隐患。_doing_it_wrong() 引导你使用更优的替代方案,提升代码质量。
  • 代码规范: _doing_it_wrong() 鼓励你遵循 WordPress 的最佳实践,编写更易于理解和维护的代码。

如何优雅地使用 _doing_it_wrong()

作为插件或主题开发者,你也可以在自己的代码中使用 _doing_it_wrong(),来标记不再推荐使用的函数、参数或者用法。

例如,假设你在插件中有一个名为 my_old_function() 的函数,你想用 my_new_function() 替代它。你可以这样做:

/**
 * @deprecated 1.0.0 Use my_new_function() instead.
 */
function my_old_function( $param1, $param2 ) {
    _doing_it_wrong( __FUNCTION__, '使用 my_new_function() 替代。', '1.0.0' );
    return my_new_function( $param1, $param2 );
}

function my_new_function( $param1, $param2 ) {
    // 新功能的实现
    return "这是新的功能";
}

// 调用旧函数
echo my_old_function("参数1","参数2");

这样,当其他开发者(或者你自己)在代码中调用 my_old_function() 时,就会收到警告信息,提醒你使用 my_new_function()

_doing_it_wrong() 的最佳实践

在使用 _doing_it_wrong() 时,请注意以下几点:

  • 只在开发环境中使用: 确保 WP_DEBUG 在生产环境中是关闭的,避免向用户显示错误信息。
  • 提供清晰的错误信息: 错误信息应该明确指出问题所在,并提供替代方案。
  • 及时更新代码: 当你收到 _doing_it_wrong() 的警告时,尽快更新你的代码,避免将来出现问题。
  • 考虑向后兼容性: 在废弃某个函数/用法时,尽量提供向后兼容性,例如通过调用替代方案来保证代码还能正常工作。

和其他类似函数的对比:_deprecated_function()_deprecated_argument()

WordPress 中还有两个与 _doing_it_wrong() 类似的函数:_deprecated_function()_deprecated_argument()。它们的作用类似,但针对不同的场景:

  • _deprecated_function(): 用于标记整个函数被废弃。
  • _deprecated_argument(): 用于标记函数中的某个参数被废弃。

可以用一个表格来更清晰地对比它们的区别:

函数 作用 适用场景
_doing_it_wrong() 标记代码中使用了不规范或过时的函数/用法。 泛指任何不推荐的使用方式。
_deprecated_function() 标记整个函数被废弃。 整个函数都不再推荐使用。
_deprecated_argument() 标记函数中的某个参数被废弃。 函数的某个参数不再推荐使用,但函数本身仍然可用。

总结:与“老妈子”和谐共处

_doing_it_wrong() 函数是 WordPress 开发中一个非常有用的工具。它可以帮助你及时发现代码中的问题,遵循最佳实践,编写更健壮、更易维护的代码。

虽然有时候它会像个“老妈子”一样唠叨你,但请记住,它是为了你好。只要你认真对待它的警告,及时更新你的代码,你就能避免掉进各种坑里,写出高质量的 WordPress 代码。

希望今天的讲解对大家有所帮助! 谢谢大家!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注