同学们,老司机我今天就来给你们扒一扒 WordPress 升级检查的核心函数 wp_check_for_updates()
的底裤!别怕,这玩意儿虽然看起来复杂,但其实就像组装乐高一样,只要你理解了每个模块的作用,就能轻松驾驭。
开场白:更新的重要性,就像吃饭一样重要!
想象一下,你的 WordPress 网站就像一辆汽车,核心、插件和主题就是汽车的各个部件。如果这些部件长时间不保养、不升级,就会出现各种问题,比如安全漏洞、性能下降,甚至直接趴窝!所以,定期检查并更新你的 WordPress 网站至关重要,就像每天吃饭一样重要!
而 wp_check_for_updates()
函数,就是那个负责告诉你:“嘿,你的车该保养了,有新的零件可以换了!” 的家伙。
第一部分:wp_check_for_updates()
函数的入口
首先,我们来看看 wp_check_for_updates()
函数在哪儿以及它主要做了些什么:
// wp-includes/update.php
function wp_check_for_updates( $args = array() ) {
global $wpdb, $wp_version, $pagenow;
if ( defined( 'WP_INSTALLING' ) ) {
return false;
}
// 确保我们拥有更新 API
if ( ! function_exists( 'plugins_api' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$defaults = array(
'suppress_plugins' => false,
'suppress_themes' => false,
'force_check' => false,
);
$args = wp_parse_args( $args, $defaults );
// 检查是否应该运行更新检查
if ( ! $args['force_check'] && ! should_check_for_updates() ) {
return false;
}
// 阻止在特定页面上运行更新检查,例如插件/主题编辑器
if ( in_array( $pagenow, array( 'plugin-editor.php', 'theme-editor.php' ), true ) ) {
return false;
}
// 核心更新检查
wp_version_check();
// 插件更新检查
if ( ! $args['suppress_plugins'] ) {
wp_update_plugins();
}
// 主题更新检查
if ( ! $args['suppress_themes'] ) {
wp_update_themes();
}
// 缓存清除
do_action( 'wp_maybe_delete_old_core_updates' );
return true;
}
简单来说,这个函数做了以下几件事:
- 各种检查: 检查是否正在安装 WordPress,是否定义了
WP_INSTALLING
常量,是否应该进行更新检查,以及当前页面是否是插件或主题编辑器页面(在这些页面上检查更新可能会导致问题)。 - 核心更新检查: 调用
wp_version_check()
函数来检查 WordPress 核心是否有更新。 - 插件更新检查: 如果
$args['suppress_plugins']
为false
,则调用wp_update_plugins()
函数来检查插件是否有更新。 - 主题更新检查: 如果
$args['suppress_themes']
为false
,则调用wp_update_themes()
函数来检查主题是否有更新。 - 缓存清除: 执行
wp_maybe_delete_old_core_updates
动作,用于清除旧的核心更新缓存。
第二部分:核心更新检查 wp_version_check()
核心更新的检查是整个更新流程的基石。让我们深入了解 wp_version_check()
函数:
// wp-includes/update.php
function wp_version_check( $deprecated = '' ) {
global $wp_version, $wp_db_version, $pagenow;
if ( ! empty( $deprecated ) ) {
_deprecated_argument( __FUNCTION__, '3.8' );
}
// 检查是否应该运行更新检查
if ( ! should_check_for_updates() ) {
return false;
}
$timeout = ( defined( 'WP_HTTP_BLOCK_EXTERNAL' ) && WP_HTTP_BLOCK_EXTERNAL ) ? 5 : 3;
$options = array(
'timeout' => $timeout,
);
$response = wp_remote_post( 'https://api.wordpress.org/core/version-check/1.7/', array(
'body' => array(
'version' => $wp_version,
'php' => phpversion(),
'locale' => get_locale(),
'mysql' => $wpdb->db_version(),
'blogs' => count( get_sites() ),
'users' => $wpdb->get_var( "SELECT COUNT(ID) FROM $wpdb->users" ),
'multisite' => is_multisite(),
'sslverify' => wp_http_validate_ssl_cert(),
),
'user-agent' => 'WordPress/' . $wp_version . '; ' . get_site_url()
), $options );
if ( is_wp_error( $response ) ) {
return false;
}
$body = trim( wp_remote_retrieve_body( $response ) );
if ( $body ) {
$decoded_response = json_decode( $body, true );
if ( is_array( $decoded_response ) ) {
$update_data = array();
foreach ( $decoded_response['offers'] as $offer ) {
$update_data[ $offer['response'] ] = $offer;
}
if ( ! empty( $update_data ) ) {
set_site_transient( 'update_core', (object) $update_data, 3600 * 12 );
}
}
}
do_action( '_after_core_updated', $response );
}
这个函数的主要步骤如下:
- 准备数据: 收集当前 WordPress 版本、PHP 版本、数据库版本、站点数量、用户数量等信息,这些信息将作为请求体发送到 WordPress.org API。
- 发起 HTTP 请求: 使用
wp_remote_post()
函数向https://api.wordpress.org/core/version-check/1.7/
发送 POST 请求。 - 处理响应: 如果请求成功,则解析 JSON 响应。响应中包含有关可用更新的信息。
- 存储更新信息: 将解析后的更新信息存储在
update_core
瞬态(transient)中,以便后续使用。瞬态就像一个临时的缓存,可以设置过期时间。
HTTP 请求的细节:
- URL:
https://api.wordpress.org/core/version-check/1.7/
这是 WordPress 官方提供的 API 端点,专门用于检查核心更新。 - 方法:
POST
使用 POST 方法发送数据,将当前 WordPress 站点的相关信息发送给 API。 - 请求体 (body): 一个关联数组,包含以下键值对:
version
: 当前 WordPress 版本。php
: 当前 PHP 版本。locale
: 当前站点语言环境。mysql
: 当前 MySQL 数据库版本。blogs
: 站点数量 (仅在多站点模式下有意义)。users
: 用户数量。multisite
: 是否为多站点。sslverify
: 是否验证 SSL 证书。
- User-Agent: 一个字符串,包含 WordPress 版本和站点 URL,用于标识请求的来源。
JSON 响应的格式:
WordPress.org API 返回的 JSON 响应是一个包含 offers
键的数组。 offers
数组包含有关可用更新的详细信息。例如:
{
"offers": [
{
"response": "upgrade",
"download": "https://downloads.wordpress.org/release/wordpress-6.4.3.zip",
"locale": "zh_CN",
"packages": {
"full": "https://downloads.wordpress.org/release/wordpress-6.4.3-zh_CN.zip",
"no_content": "https://downloads.wordpress.org/release/wordpress-6.4.3-no-content-zh_CN.zip",
"new_bundled": "https://downloads.wordpress.org/release/wordpress-6.4.3-new-bundled-zh_CN.zip"
},
"current": "6.4.2",
"version": "6.4.3",
"php_version": "7.0",
"mysql_version": "5.0",
"new_files": "5.0",
"package": "https://downloads.wordpress.org/release/wordpress-6.4.3-zh_CN.zip",
"md5": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"sha1": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
]
}
其中,response
字段表示更新类型(例如,upgrade
表示需要升级)。其他字段包含有关下载链接、版本号、PHP 和 MySQL 版本要求等信息。
should_check_for_updates()
函数:
这个函数决定是否应该进行更新检查。它基于一些配置和时间间隔,以避免频繁地向 WordPress.org API 发送请求。
// wp-includes/update.php
function should_check_for_updates() {
$time_not_checked = get_site_transient( 'update_core' );
if ( isset( $time_not_checked->last_checked ) && ( time() - $time_not_checked->last_checked < 3600 ) ) {
return false;
}
return true;
}
默认情况下,每小时检查一次核心更新。这个时间间隔可以通过过滤器进行修改。
第三部分:插件更新检查 wp_update_plugins()
插件更新的检查稍微复杂一些,因为它需要检查每个已安装的插件。
// wp-includes/update.php
function wp_update_plugins() {
global $wp_version;
$plugins = get_plugins();
$active = get_option( 'active_plugins', array() );
$current = get_site_transient( 'update_plugins' );
if ( ! is_array( $plugins ) ) {
return false;
}
$to_send = compact( 'plugins', 'active', 'wp_version' );
$options = array(
'timeout' => ( defined( 'WP_HTTP_BLOCK_EXTERNAL' ) && WP_HTTP_BLOCK_EXTERNAL ) ? 5 : 3,
);
$response = wp_remote_post( admin_url( 'plugin-install.php' ), array(
'body' => array(
'action' => 'update-check',
'plugins' => wp_json_encode( $to_send ),
),
'user-agent' => 'WordPress/' . $wp_version . '; ' . get_site_url()
), $options );
if ( is_wp_error( $response ) ) {
return false;
}
$plugins = maybe_unserialize( wp_remote_retrieve_body( $response ) );
if ( is_object( $plugins ) ) {
set_site_transient( 'update_plugins', $plugins, 3600 * 12 );
} elseif ( $plugins ) {
set_site_transient( 'update_plugins', new stdClass, 3600 * 12 );
}
do_action( '_after_plugin_updated', $response );
}
这个函数的主要步骤如下:
- 获取插件信息: 使用
get_plugins()
函数获取所有已安装的插件信息。使用get_option( 'active_plugins' )
获取所有激活的插件信息。 - 准备数据: 将所有插件信息、激活插件信息和 WordPress 版本打包成一个数组
$to_send
。 - 发起 HTTP 请求: 使用
wp_remote_post()
函数向admin_url( 'plugin-install.php' )
发送 POST 请求。 注意,这里发送请求到 WordPress 站点自身的plugin-install.php
文件,并设置action
参数为update-check
。 - 处理响应: 如果请求成功,则反序列化响应内容。响应中包含有关可用插件更新的信息。
- 存储更新信息: 将解析后的更新信息存储在
update_plugins
瞬态中。
HTTP 请求的细节:
- URL:
admin_url( 'plugin-install.php' )
指向 WordPress 站点自身的plugin-install.php
文件。 - 方法:
POST
- 请求体 (body): 一个关联数组,包含以下键值对:
action
:update-check
指示plugin-install.php
执行更新检查操作。plugins
: 使用wp_json_encode()
函数将$to_send
数组编码为 JSON 字符串。
- User-Agent: 同核心更新检查。
JSON 响应的格式:
plugin-install.php
返回的响应是一个序列化的 PHP 对象,其中包含有关可用插件更新的信息。 这个对象通常包含以下属性:
last_checked
: 上次检查更新的时间戳。checked
: 一个关联数组,其中键是插件的文件路径(例如,my-plugin/my-plugin.php
),值是插件的当前版本。response
: 一个关联数组,其中键是插件的文件路径,值是包含更新信息的对象。 如果没有更新,则该插件的文件路径将不会出现在这个数组中。
第四部分:主题更新检查 wp_update_themes()
主题更新的检查与插件更新的检查类似,只是操作对象变成了主题。
// wp-includes/update.php
function wp_update_themes() {
global $wp_version;
$themes = wp_get_themes();
$current = get_site_transient( 'update_themes' );
$options = array(
'timeout' => ( defined( 'WP_HTTP_BLOCK_EXTERNAL' ) && WP_HTTP_BLOCK_EXTERNAL ) ? 5 : 3,
);
$to_send = array(
'themes' => array(),
'wp_version' => $wp_version,
);
foreach ( $themes as $theme ) {
$to_send['themes'][ $theme->get_stylesheet() ] = array(
'Version' => $theme->get( 'Version' ),
'Name' => $theme->get( 'Name' ),
'Author' => $theme->get( 'Author' )
);
}
$response = wp_remote_post( admin_url( 'theme-install.php' ), array(
'body' => array(
'action' => 'update-check',
'themes' => wp_json_encode( $to_send ),
),
'user-agent' => 'WordPress/' . $wp_version . '; ' . get_site_url()
), $options );
if ( is_wp_error( $response ) ) {
return false;
}
$themes = maybe_unserialize( wp_remote_retrieve_body( $response ) );
if ( is_object( $themes ) ) {
set_site_transient( 'update_themes', $themes, 3600 * 12 );
} elseif ( $themes ) {
set_site_transient( 'update_themes', new stdClass, 3600 * 12 );
}
do_action( '_after_theme_updated', $response );
}
这个函数的主要步骤如下:
- 获取主题信息: 使用
wp_get_themes()
函数获取所有已安装的主题信息。 - 准备数据: 将所有主题信息和 WordPress 版本打包成一个数组
$to_send
。 - 发起 HTTP 请求: 使用
wp_remote_post()
函数向admin_url( 'theme-install.php' )
发送 POST 请求。 注意,这里发送请求到 WordPress 站点自身的theme-install.php
文件,并设置action
参数为update-check
。 - 处理响应: 如果请求成功,则反序列化响应内容。响应中包含有关可用主题更新的信息。
- 存储更新信息: 将解析后的更新信息存储在
update_themes
瞬态中。
HTTP 请求的细节:
- URL:
admin_url( 'theme-install.php' )
指向 WordPress 站点自身的theme-install.php
文件。 - 方法:
POST
- 请求体 (body): 一个关联数组,包含以下键值对:
action
:update-check
指示theme-install.php
执行更新检查操作。themes
: 使用wp_json_encode()
函数将$to_send
数组编码为 JSON 字符串。
- User-Agent: 同核心更新检查。
JSON 响应的格式:
theme-install.php
返回的响应是一个序列化的 PHP 对象,其中包含有关可用主题更新的信息。 这个对象通常包含以下属性:
last_checked
: 上次检查更新的时间戳。checked
: 一个关联数组,其中键是主题的样式表目录名(例如,twentytwentyfour
),值是主题的当前版本。response
: 一个关联数组,其中键是主题的样式表目录名,值是包含更新信息的对象。 如果没有更新,则该主题的样式表目录名将不会出现在这个数组中。
第五部分:总结与思考
总的来说,wp_check_for_updates()
函数通过以下步骤来检查更新:
- 准备: 检查各种前提条件,确保可以进行更新检查。
- 核心更新: 调用
wp_version_check()
函数,与 WordPress.org API 交互,检查核心更新。 - 插件更新: 调用
wp_update_plugins()
函数,与 WordPress 站点自身的plugin-install.php
交互,检查插件更新。 - 主题更新: 调用
wp_update_themes()
函数,与 WordPress 站点自身的theme-install.php
交互,检查主题更新。 - 存储: 将更新信息存储在瞬态中,以便后续使用。
与 WordPress.org API 交互的方式总结:
更新类型 | API 端点 | 请求方法 | 请求体 | 响应格式 |
---|---|---|---|---|
核心更新 | https://api.wordpress.org/core/version-check/1.7/ |
POST |
包含 WordPress 版本、PHP 版本、数据库版本、站点数量、用户数量等信息。 | JSON,包含更新信息 |
插件更新 | admin_url( 'plugin-install.php' ) |
POST |
包含所有已安装的插件信息和激活插件信息。action 参数设置为 update-check 。 |
序列化的 PHP 对象,包含更新信息 |
主题更新 | admin_url( 'theme-install.php' ) |
POST |
包含所有已安装的主题信息。action 参数设置为 update-check 。 |
序列化的 PHP 对象,包含更新信息 |
一些思考:
- 性能: 频繁的更新检查可能会影响网站性能。因此,WordPress 使用瞬态来缓存更新信息,并限制更新检查的频率。
- 安全性: 更新检查过程涉及与外部 API 的通信,需要注意安全性问题。WordPress 使用 HTTPS 协议来保护通信安全。
- 可扩展性: WordPress 允许通过过滤器来修改更新检查的行为,例如修改 API 端点、修改更新检查的频率等。
希望通过今天的讲解,你们对 WordPress 的更新检查机制有了更深入的了解。记住,保持你的 WordPress 网站更新,就像保持你的身体健康一样重要!下次再见!