WordPress 源码解析【1】

<?php
/**
 * Front to the WordPress application. This file doesn't do anything, but loads
 * wp-blog-header.php which does and tells WordPress to load the theme.
 *
 * @package WordPress
 */

/**
 * Tells WordPress to load the WordPress theme and output it.
 *
 * @var bool
 */
define( 'WP_USE_THEMES', true ); // 定义常量 WP_USE_THEMES 为 true,表示启用主题支持

/** Loads the WordPress Environment and Template */
require __DIR__ . '/wp-blog-header.php'; // 引入 wp-blog-header.php 文件,加载 WordPress 环境和模板

逐行
解析:

  1. <?php:开始 PHP 代码块。
  2. /** ... */:注释,描述该文件的功能,说明这是 WordPress 应用程序的前端文件。
  3. define( 'WP_USE_THEMES', true );:定义一个常量 WP_USE_THEMES,设置为 true,表示启用主题。
  4. require __DIR__ . '/wp-blog-header.php';:引入 wp-blog-header.php 文件,加载 WordPress 的环境和模板。__DIR__ 是当前文件的目录路径。

这段代码是 WordPress 的引导文件 wp-load.php,主要用于设置 ABSPATH 常量并加载 wp-config.php 文件。以下是逐行

解析:

<?php
/**
 * Bootstrap file for setting the ABSPATH constant
 * and loading the wp-config.php file. The wp-config.php
 * file will then load the wp-settings.php file, which
 * will then set up the WordPress environment.
 *
 * If the wp-config.php file is not found then an error
 * will be displayed asking the visitor to set up the
 * wp-config.php file.
 *
 * Will also search for wp-config.php in WordPress' parent
 * directory to allow the WordPress directory to remain
 * untouched.
 *
 * @package WordPress
 */
  • 这部分是文件的文档注释,描述了文件的功能和用途。
/** Define ABSPATH as this file's directory */
if ( ! defined( 'ABSPATH' ) ) {
    define( 'ABSPATH', __DIR__ . '/' );
}
  • 检查 ABSPATH 常量是否已定义,如果没有,则将其定义为当前文件的目录。
/*
 * The error_reporting() function can be disabled in php.ini. On systems where that is the case,
 * it's best to add a dummy function to the wp-config.php file, but as this call to the function
 * is run prior to wp-config.php loading, it is wrapped in a function_exists() check.
 */
if ( function_exists( 'error_reporting' ) ) {
    /*
     * Initialize error reporting to a known set of levels.
     *
     * This will be adapted in wp_debug_mode() located in wp-includes/load.php based on WP_DEBUG.
     * @see https://www.php.net/manual/en/errorfunc.constants.php List of known error levels.
     */
    error_reporting( E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR );
}
  • 检查 error_reporting 函数是否存在,如果存在,则初始化错误报告级别,以便在开发过程中捕获错误。
/*
 * If wp-config.php exists in the WordPress root, or if it exists in the root and wp-settings.php
 * doesn't, load wp-config.php. The secondary check for wp-settings.php has the added benefit
 * of avoiding cases where the current directory is a nested installation, e.g. / is WordPress(a)
 * and /blog/ is WordPress(b).
 *
 * If neither set of conditions is true, initiate loading the setup process.
 */
if ( file_exists( ABSPATH . 'wp-config.php' ) ) {

    /** The config file resides in ABSPATH */
    require_once ABSPATH . 'wp-config.php';

} elseif ( @file_exists( dirname( ABSPATH ) . '/wp-config.php' ) && ! @file_exists( dirname( ABSPATH ) . '/wp-settings.php' ) ) {

    /** The config file resides one level above ABSPATH but is not part of another installation */
    require_once dirname( ABSPATH ) . '/wp-config.php';

} else {
  • 检查 wp-config.php 文件是否存在于 WordPress 根目录中。如果存在,则加载该文件。如果不存在,则检查其父目录中是否存在该文件,并且确保 wp-settings.php 不存在,以避免嵌套安装的情况。
    // A config file doesn't exist.

    define( 'WPINC', 'wp-includes' );
    require_once ABSPATH . WPINC . '/version.php';
    require_once ABSPATH . WPINC . '/compat.php';
    require_once ABSPATH . WPINC . '/load.php';

    // Check for the required PHP version and for the MySQL extension or a database drop-in.
    wp_check_php_mysql_versions();

    // Standardize $_SERVER variables across setups.
    wp_fix_server_vars();

    define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
    require_once ABSPATH . WPINC . '/functions.php';
  • 如果 wp-config.php 文件不存在,则定义 WPINC 常量并加载一些必要的文件,包括版本信息、兼容性文件和加载文件。接着检查 PHP 版本和 MySQL 扩展,并标准化 $_SERVER 变量。
    $path = wp_guess_url() . '/wp-admin/setup-config.php';

    // Redirect to setup-config.php.
    if ( ! str_contains( $_SERVER['REQUEST_URI'], 'setup-config' ) ) {
        header( 'Location: ' . $path );
        exit;
    }
  • 生成 setup-config.php 的路径,并检查当前请求的 URI 是否包含 setup-config,如果没有,则重定向到该路径。
    wp_load_translations_early();

    // Die with an error message.
    $die = '<p>' . sprintf(
        /* translators:
        __( "There doesn't seem to be a
        '<code>wp-config.php</code>'
    ) . '</p>';
    $die .= '<p>' . sprintf(
        /* translators: 1: Documentation URL, 2: wp-config.php */
        __( 'Need more help? <a href=
        __( 'https://developer.wordpress.org/advanced-administration/wordpress/wp-config/' ),
        '<code>wp-config.php</code>'
    ) . '</p>';
    $die .= '<p>' . sprintf(
        /* translators:
        __( "You can create a
        '<code>wp-config.php</code>'
    ) . '</p>';
    $die .= '<p><a href="' . $path . '" class="button button-large">' . __( 'Create a Configuration File' ) . '</a></p>';

    wp_die( $die, __( 'WordPress &rsaquo; Error' ) );
}
  • 加载翻译文件,并构建一个错误消息,提示用户缺少 wp-config.php 文件。最后调用 wp_die() 函数终止执行并显示错误信息。

这段代码的主要目的是确保 WordPress 环境的正确设置,并在缺少必要配置文件时提供用户友好的错误提示。


以下是对 wp-includes/user.php 文件中 _wp_get_current_user 函数的逐行

解析:

/**
 * Retrieves the current user object.
 *
 * Will set the current user, if the current user is not set. The current user
 * will be set to the logged-in person. If no user is logged-in, then it will
 * set the current user to 0, which is invalid and won't have any permissions.
 *
 * This function is used by the pluggable functions wp_get_current_user() and
 * get_currentuserinfo(), the latter of which is deprecated but used for backward
 * compatibility.
 *
 * @since 4.5.0
 * @access private
 *
 * @see wp_get_current_user()
 * @global WP_User $current_user Checks if the current user is set.
 *
 * @return WP_User Current WP_User instance.
 */
  • 这是函数的文档注释,描述了函数的功能、使用场景和返回值。它说明了如何获取当前用户对象,并在没有用户登录时将其设置为无效值(0)。
function _wp_get_current_user() {
    global $current_user;
  • 定义了 _wp_get_current_user 函数,并声明使用全局变量 $current_user,该变量用于存储当前用户对象。
    if ( ! empty( $current_user ) ) {
        if ( $current_user instanceof WP_User ) {
            return $current_user;
        }
  • 检查 $current_user 是否不为空。如果不为空且是 WP_User 的实例,则直接返回当前用户对象。
        // Upgrade stdClass to WP_User.
        if ( is_object( $current_user ) && isset( $current_user->ID ) ) {
            $cur_id       = $current_user->ID;
            $current_user = null;
            wp_set_current_user( $cur_id );
            return $current_user;
        }
  • 如果 $current_user 是一个对象且具有 ID 属性,则将其视为需要升级的对象。保存当前用户的 ID,清空 $current_user,然后调用 wp_set_current_user 函数设置当前用户为该 ID,并返回当前用户(此时仍为 null)。
        // $current_user has a junk value. Force to WP_User with ID 0.
        $current_user = null;
        wp_set_current_user( 0 );
        return $current_user;
    }
  • 如果 $current_user 具有无效值,则将其设置为 null,并将当前用户强制设置为 ID 为 0 的用户(无效用户),然后返回当前用户(仍为 null)。
    if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
        wp_set_current_user( 0 );
        return $current_user;
    }
  • 检查是否为 XML-RPC 请求。如果是,则将当前用户设置为 ID 为 0 的用户,并返回当前用户。
    /**
     * Filters the current user.
     *
     * The default filters use this to determine the current user from the
     * request's cookies, if available.
     *
     * Returning a value of false will effectively short-circuit setting
     * the current user.
     *
     * @since 3.9.0
     *
     * @param int|false $user_id User ID if one has been determined, false otherwise.
     */
    $user_id = apply_filters( 'determine_current_user', false );
  • 通过 apply_filters 调用 determine_current_user 过滤器,尝试从请求的 cookies 中确定当前用户的 ID。如果没有确定到用户 ID,则返回 false。
    if ( ! $user_id ) {
        wp_set_current_user( 0 );
        return $current_user;
    }
  • 如果没有找到用户 ID,则将当前用户设置为 ID 为 0 的用户,并返回当前用户。
    wp_set_current_user( $user_id );
  • 如果找到了用户 ID,则调用 wp_set_current_user 函数设置当前用户为该 ID。
    return $current_user;
}
  • 最后返回当前用户对象。

总结

该函数的主要功能是获取当前用户对象,并在必要时设置当前用户。它处理了多种情况,包括用户未登录、用户对象无效以及 XML-RPC 请求等。通过使用过滤器,函数还允许开发者自定义当前用户的确定方式。


在 WordPress 中,过滤器(filter)机制是一种允许开发者修改或处理数据的机制。通过使用过滤器,开发者可以在特定的点插入自定义代码,以改变函数的行为或输出。以下是过滤器机制的详细

解析:

/**
 * Filters the current user.
 *
 * The default filters use this to determine the current user from the
 * request's cookies, if available.
 *
 * Returning a value of false will effectively short-circuit setting
 * the current user.
 *
 * @since 3.9.0
 *
 * @param int|false $user_id User ID if one has been determined, false otherwise.
 */
$user_id = apply_filters( 'determine_current_user', false );
if ( ! $user_id ) {
    wp_set_current_user( 0 );
    return $current_user;
}

过滤器机制的工作原理

  • 定义过滤器
  • 在代码中,apply_filters 函数用于调用一个名为 'determine_current_user' 的过滤器。这个过滤器的作用是允许其他开发者在这个点插入自定义逻辑,以确定当前用户的 ID。
  • 传递参数
  • apply_filters 函数的第二个参数是默认值,这里是 false。这意味着如果没有其他代码修改这个值,$user_id 将保持为 false
  • 注册过滤器
  • 开发者可以使用 add_filter 函数来注册一个自定义的过滤器。例如:
    add_filter( ‘determine_current_user’, ‘my_custom_user_function’ );
  • 在这个例子中,my_custom_user_function 是一个自定义函数,它会在调用 apply_filters 时被执行。这个函数可以根据请求的 cookies 或其他条件来返回一个用户 ID。
  • 返回值
  • 如果 my_custom_user_function 返回一个有效的用户 ID,$user_id 将被设置为该 ID。如果返回 false,则 $user_id 仍然是 false
  • 短路逻辑
  • 如果 $user_idfalse,代码会执行 wp_set_current_user( 0 ),将当前用户设置为无效用户(ID 为 0),并返回当前用户对象。

总结

过滤器机制使得 WordPress 的功能具有高度的可扩展性和灵活性。开发者可以通过注册自定义过滤器来改变核心功能的行为,而不需要直接修改核心代码。这种设计模式使得 WordPress 能够支持大量的插件和主题,允许开发者根据自己的需求进行定制。


0 0 投票数
Article Rating
订阅评论
提醒
0 评论
最多投票
最新 最旧
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x