嘿,各位代码爱好者!今天咱们来聊聊 WordPress 里面一个相当重要的函数:_wp_check_for_updates()
。别看名字好像很长,其实它干的事情很简单,就是默默地检查 WordPress 的核心、插件和主题有没有新版本。而它背后的机制,则离不开 WordPress 的定时任务系统 wp_cron
。
咱们今天要像剥洋葱一样,一层一层地扒开这个函数的源码,看看它是怎么通过 wp_cron
来完成更新检查任务的。放心,我会尽量用大白话,保证你听得懂,看得明白。
开场白:为什么需要自动更新检查?
想象一下,你辛辛苦苦搭建了一个 WordPress 网站,运行了几个月后,突然发现网站被人黑了,或者出现了莫名其妙的 bug。事后调查发现,罪魁祸首竟然是使用了过时的插件或者主题。
这是多么令人沮丧的事情!为了避免这种情况发生,我们需要定期检查 WordPress 及其组件的更新。手动检查当然可以,但是谁会每天都记得去检查呢?所以,自动更新检查就显得尤为重要了。
_wp_check_for_updates()
函数:更新检查的指挥官
_wp_check_for_updates()
函数位于 wp-includes/update.php
文件中。这个函数是整个更新检查流程的指挥官,它负责协调各个组件,获取更新信息,并将其存储到数据库中。
让我们先来看看这个函数的大致结构:
function _wp_check_for_updates() {
global $wpdb;
if ( ! is_network_admin() && ! is_user_member_of_blog() ) {
return;
}
if ( get_site_transient( 'doing_wp_cron' ) ) {
return;
}
$current = get_site_transient( 'update_core' );
if ( isset( $current->last_checked ) && ( time() - $current->last_checked < 3600 ) ) {
return;
}
wp_version_check();
wp_update_plugins();
wp_update_themes();
/**
* Fires after the WordPress update check is run.
*
* @since 3.0.0
*
* @param WP_Upgrader|null $upgrader WP_Upgrader instance, or null
* if not available.
*/
do_action( 'wp_maybe_update');
}
看起来是不是有点长?别怕,我们来逐行分析:
-
global $wpdb;
: 这一行不用多说,就是引入全局的$wpdb
对象,用于执行数据库操作。 -
if ( ! is_network_admin() && ! is_user_member_of_blog() ) { return; }
: 这个条件判断语句用于检查当前用户是否有权限进行更新检查。只有网络管理员(在 WordPress Multisite 环境下)或者当前博客的管理员才能执行更新检查。 -
if ( get_site_transient( 'doing_wp_cron' ) ) { return; }
: 这是个很重要的判断!它检查一个名为doing_wp_cron
的site_transient
是否存在。site_transient
是一种在数据库中存储临时数据的方式,用于避免重复执行某些耗时的操作。如果doing_wp_cron
存在,说明已经有另一个wp_cron
进程正在运行,那么就直接返回,避免并发执行更新检查。 -
$current = get_site_transient( 'update_core' );
: 获取 WordPress 核心的更新信息。这些信息包括当前 WordPress 版本、最新版本、更新包下载地址等等。 -
if ( isset( $current->last_checked ) && ( time() - $current->last_checked < 3600 ) ) { return; }
: 这是一个时间间隔检查。它检查上次更新检查的时间是否超过了一个小时(3600 秒)。如果没超过,说明最近已经检查过了,就没必要再次检查了。这个机制可以避免过于频繁地请求 WordPress 官方服务器,减轻服务器压力。 -
wp_version_check();
: 这是核心函数之一,用于检查 WordPress 核心是否有新版本。 -
wp_update_plugins();
: 用于检查插件是否有新版本。 -
wp_update_themes();
: 用于检查主题是否有新版本。 -
do_action( 'wp_maybe_update');
: 这是一个钩子函数,允许其他插件或者主题在更新检查之后执行一些自定义的操作。
wp_cron
:幕后的定时任务调度员
好了,我们已经了解了 _wp_check_for_updates()
函数的作用,但是还有一个关键问题:这个函数是什么时候被调用的呢?答案就是 wp_cron
。
wp_cron
是 WordPress 自带的一个简单的定时任务系统。它实际上并不是一个真正的 cron 守护进程,而是一种模拟的 cron 机制。它的工作原理是:当有用户访问 WordPress 网站时,WordPress 会检查是否有需要执行的定时任务。如果有,就执行这些任务。
那么,_wp_check_for_updates()
函数是如何被添加到 wp_cron
的任务列表中的呢?
这通常是通过 wp_schedule_event()
函数来实现的。这个函数可以将一个函数添加到 wp_cron
的任务列表中,并指定执行的时间间隔。
例如,在 wp-includes/cron.php
文件中,你可以找到类似这样的代码:
if ( ! wp_next_scheduled( 'wp_version_check' ) ) {
wp_schedule_event( time(), 'twicedaily', 'wp_version_check' );
}
这段代码的意思是:如果 wp_version_check
这个函数还没有被添加到 wp_cron
的任务列表中,那么就将它添加到任务列表中,并指定每隔 12 小时(twicedaily
)执行一次。
wp_version_check
实际上是 _wp_version_check
的一个包装器,最终还是会调用 _wp_check_for_updates()
函数。
深入 wp_version_check()
:WordPress 核心更新检查
wp_version_check()
函数是负责检查 WordPress 核心是否有新版本的。它的主要工作流程如下:
-
获取当前 WordPress 版本信息: 这个很简单,直接从
$wp_version
全局变量中获取。 -
构建 API 请求:
wp_version_check()
函数会向 WordPress 官方 API 发送一个 HTTP 请求,请求中包含了当前 WordPress 版本信息、当前站点信息等等。 -
发送 HTTP 请求: 使用
wp_remote_post()
函数发送 HTTP 请求。 -
解析 API 响应: API 响应通常是一个 JSON 格式的数据,包含了最新 WordPress 版本信息、更新包下载地址等等。
-
存储更新信息: 将解析后的更新信息存储到
site_transient
中,方便后续使用。
让我们来看看 wp_version_check()
函数的关键代码片段:
function wp_version_check( $deprecated = '' ) {
global $wp_version, $wp_local_package;
if ( ! empty( $deprecated ) ) {
_deprecated_argument( __FUNCTION__, '3.8', null );
}
if ( get_site_transient( 'doing_wp_cron' ) ) {
return false;
}
$timeout = 3;
$options = array(
'timeout' => $timeout,
'body' => array(
'version' => $wp_version,
'php' => phpversion(),
'locale' => get_locale(),
'mysql' => $wpdb->db_version(),
'blogs' => $wpdb->blogid,
'users' => $wpdb->get_var( "SELECT COUNT(ID) FROM $wpdb->users" ),
'multisite_enabled' => is_multisite(),
'initial_db_version' => get_site_option( 'initial_db_version' ),
),
'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url()
);
// Include an MD5 hash of the WordPress package.
if ( isset( $wp_local_package ) ) {
$options['body']['local_package'] = md5_file( ABSPATH . WPINC . '/version.php' );
}
$url = 'https://api.wordpress.org/core/version-check/1.7/?' . http_build_query( $options['body'], '', '&' );
$response = wp_remote_get( $url, $options );
if ( is_wp_error( $response ) ) {
return false;
}
$body = wp_remote_retrieve_body( $response );
if ( empty( $body ) ) {
return false;
}
$decoded_response = json_decode( $body );
if ( ! is_object( $decoded_response ) ) {
return false;
}
if ( isset( $decoded_response->offers ) && is_array( $decoded_response->offers ) ) {
foreach ( $decoded_response->offers as &$offer ) {
if ( isset( $offer->packages ) && ! is_array( $offer->packages ) ) {
$offer->packages = array( $offer->packages );
}
}
}
set_site_transient( 'update_core', $decoded_response, 3 * HOUR_IN_SECONDS );
return true;
}
注意看 $options['body']
数组,这里面包含了发送给 WordPress 官方 API 的数据。 'url'
变量定义了 API 端点。 set_site_transient( 'update_core', $decoded_response, 3 * HOUR_IN_SECONDS );
这行代码将 API 响应存储到 site_transient
中,过期时间为 3 小时。
wp_update_plugins()
和 wp_update_themes()
:插件和主题更新检查
wp_update_plugins()
和 wp_update_themes()
函数的原理与 wp_version_check()
类似,都是通过发送 HTTP 请求到 WordPress 官方 API 或者第三方 API,获取插件和主题的更新信息,并将这些信息存储到 site_transient
中。
不同之处在于:
wp_update_plugins()
函数需要遍历所有已安装的插件,并为每个插件构建 API 请求。wp_update_themes()
函数需要遍历所有已安装的主题,并为每个主题构建 API 请求。- 插件和主题的 API 端点可能不同,有些插件和主题可能使用 WordPress 官方 API,有些则可能使用第三方 API。
wp_cron
的一些问题与优化
虽然 wp_cron
用起来很方便,但是它也有一些局限性:
-
依赖用户访问:
wp_cron
只有在有用户访问 WordPress 网站时才会执行。如果网站访问量很低,那么定时任务可能无法按时执行。 -
性能问题: 每次有用户访问网站时,WordPress 都会检查是否有需要执行的定时任务,这会增加服务器的负担。
为了解决这些问题,可以考虑以下优化方案:
- 使用真正的 cron 守护进程: 可以将
wp_cron
禁用,然后使用服务器上的真正的 cron 守护进程来定时执行wp-cron.php
文件。这样可以确保定时任务按时执行,并且不会影响网站的性能。 - 使用第三方插件: 有一些第三方插件可以优化
wp_cron
的性能,例如 WP Crontrol 插件。
总结
好了,今天的讲座就到这里。我们一起深入剖析了 WordPress 的 _wp_check_for_updates()
函数,了解了它是如何通过 wp_cron
来检查更新的。
让我们来总结一下:
函数/机制 | 作用 |
---|---|
_wp_check_for_updates() |
更新检查的指挥官,负责协调各个组件,获取更新信息,并将其存储到数据库中。 |
wp_cron |
WordPress 自带的定时任务系统,用于定时执行某些任务。 |
wp_version_check() |
检查 WordPress 核心是否有新版本。 |
wp_update_plugins() |
检查插件是否有新版本。 |
wp_update_themes() |
检查主题是否有新版本。 |
site_transient |
在数据库中存储临时数据,用于避免重复执行某些耗时的操作。 |
希望今天的讲座对你有所帮助。记住,理解 WordPress 的底层机制,可以帮助你更好地使用和定制 WordPress,打造出更强大的网站。下次再见!