普通视图

发现新文章,点击刷新页面。
昨天以前首页

网站速度很慢?使用 WordPress 短时缓存(Transients)来优化数据库查询和 HTTP 响应!

2024年11月18日 22:40

每个人都想要一个速度很快的网站,网站速度越快,用户停留和点击页面或购买产品的时间就越长,加快网站速度的方法之一是开启缓存,而缓存背后的逻辑就是存储信息,更具体一点说,就是找到一个比连接数据库更快的存储信息的地方。

在 WordPress 中,如果一些复杂的 SQL 查询或者耗时的 HTTP 请求,其实它们的结果在一定时间内是不变的,那么为了网站速度,如果把这些操作的结果缓存起来,这样下次进行同样的 SQL 查询和 HTTP 请求的时候,就可以直接从缓存中获取数据,从而可以显著加快网站的速度,当然一些复杂计算的结果也可以通过该方法进行缓存。

 WordPress Transients

那么在 WordPress 中如何快速缓存 SQL 查询和 HTTP 响应呢?这个时候就要用到 WordPress 的短时缓存(Transients)功能。

什么是短时缓存(Transients)

我们知道 WordPress 缓存有多种类型,比如对象缓存、浏览器缓存、页面缓存甚至数据库缓存,每种类型都有其用途和设置步骤,比如需要安装插件和更改服务器配置以启用对象缓存等。

那么今天介绍的 Transients API,是 WordPress 用于在页面加载期间临时存储 WordPress 中的信息,Transients 本身是“短暂的”或“临时的”意思,那么 Transients API 可以理解为临时缓存或者短暂缓存的意思,我这里将它翻译成短时缓存,它是 WordPress 用来缓存一些复杂的 SQL 查询和运算结果的最简单的方法。

它给这些需要缓存的数据一个过期时间,并且时间一到就会自动删除,所以在制作 WordPress 插件的时候,需要存储一些有一定生命周期的数据的时候,Transients API 就是最好的选择。

简单说,Transients 是一种非常强大的工具,它不仅可以用来避免对页面内容进行不必要的数据库请求,还可以加快生成复杂标记的速度并加快耗时的第三方 API 请求。 

Transients 相关函数

首先说下,Transients 的存储,如果服务器开启了 #Memcached#,那么缓存的数据就会存在 Memcached 的内存中,如果没有开启的话,则存储到 WordPress 数据库的 Options 表中

所以它接口函数和 WordPress 的 Option API get_option, add_option, update_option, delete_option))基本一样,唯一区别就是 Transients API 有一个过期时间,并且它没有 add 方法,统一合并成 set 了,所以 WordPress Transients API 有以下三个函数:

// 保存一个数据到短时缓存中
set_transient( string $transient, mixed $value, int $expiration )

// 从短时缓存中获取一个数据
get_transient( string $transient )

// 从短时缓存中删除一个数据
delete_transient( string $transient )

函数的使用过非常简单,这里不做详细解释,简单注意下两点:

  1. 如果使用获取短时缓存函数 get_transient 去获取数据,已经过期或者不存在的情况下是返回 false 的。
  2. 完全不用担心 Transients API 会将数据库的 Options 表塞满数据,因为临时变量一旦过期,下次获取的时候就会自动被删除,并且上面也说了如果服务器开启了 #Memcached#,那么缓存的数据就会存在 Memcached 的内存中。

一个应用 Transients 的例子

🙋‍♀️🌰 假设你要获取博客的浏览最高的 10 篇文章,文章的浏览数据一般是存在 PostMeta 表中,所以这样的数据库查询会用到 Posts 表和 PostMeta 表进行联表查询,如果文章数量比较多的情况下,这样的查询一般是比较慢的。

而事情的另一面,博客浏览最高的 10 篇文章一般来说在一段时间(比如:12小时)之内很可能是不变的,所以这个功能最适合使用 Transients API 进行缓存了:

$top_10_posts = get_transient('top_10_posts');

if(false === $top_10_posts){ // 临时变量过期了或者根本就没有创建

	// 通过 SQL 查询获取流量最高的 10 篇文章,
	$top_10_posts = wpjam_get_top_viewd_posts(10);

	// 把临时变量存到数据库中,时间为 12 个小时
	set_transient('top_10_posts', $top_10_posts, HOUR_IN_SECONDS*12);
}

我们首先使用 get_transient('top_10_posts') 函数从缓存中看看有没有缓存,如果没有,该函数是返回 false 的。

程序获取缓存结果为 false 的时候,就通过 wpjam_get_top_viewd_posts 这个带有复杂 SQL 的函数获取文章,然后通过函数 set_transient('top_10_posts', $top_10_posts, HOUR_IN_SECONDS*12) 存到缓存中,并且过期时间设置为 12 小时。

这样下次再去获取浏览最高的文章,直接从缓存中返回了,就不用担心不用担心数据库查询过慢的问题了。

使用 Hook 删除短时缓存

如果由于某种原因某篇流行文章删除,这个时候可能流量最高的文章都可能发生变化,我们就可以使用 delete_transient 函数把这个临时变量删除了,这样我们可以使用 WordPress 的删除文章的 Hook delete_post 进行操作:

add_action('delete_post', fn() => delete_transient('top_10_posts'));

如果你想有新文章发布了,虽然这时候一般不会影响浏览最高的文章列表,但是如果想,也可以把缓存清理了,这时候用到是 publish_post Hook:

add_action('publish_post', fn() => delete_transient('top_10_posts'));

WPJAM 终极方法

虽然 Transients API 的使用非常简单,它主要逻辑就是首先使用 get_transient() 函数获取缓存,=如果没有,再通过函数 set_transient() 将数据存到缓存中。

但是这里都有要写个判断,并且缓存的名称也要重复写两次,对于我这么懒的程序是不可能接受的,另外它的逻辑感觉上在破坏了程序的主逻辑,所以我在 #WPJAM Basic# 中集成了 wpjam_transient 函数,它通过回调的方式,让只需一步就实现 WordPress 短时缓存:

首先我们实现看看我的 wpjam_transient 函数的实现:

function wpjam_transient($name, $callback, $expire=86400){
	$data	= get_transient($name);

	if($data === false){
		$data	= $callback();

		if(!is_wp_error($data)){
			set_transient($name, $data, $expire);
		} 
	}

	return $data;
}

可以看到 wpjam_transient 函数把获取和设置短时缓存的函数都内置到了函数中,你只需要关注你程序的主逻辑,所以上面的缓存的浏览最高的 10 篇文章的代码可以简化为 1 行代码:

wpjam_transient('top_10_posts', fn()=> wpjam_get_top_viewd_posts(10), HOUR_IN_SECONDS*12);

是不是非常简洁。🤭

总结

WordPress 短时缓存(Transients API)是 WordPress 用于在页面加载期间临时存储 WordPress 中的信息,该功能用的好,特别是用于缓存复杂的 SQL 查询,耗时 HTTP 请求,以及复杂计算的结果等,对于站点有明显的提高,#WPJAM Basic# 集成的 wpjam_transient 函数进一步提高使用效率,只需一步就实现 WordPress 短时缓存。

WordPress 中如何设置全局选项?一文详解 WordPress 的 Option 功能!

2024年10月24日 22:36

对于进行 WordPress 开发来说,肯定会了解到的一个开发功能就是 WordPress 设置选项的创建,访问,修改和删除,比如主题和插件的设置选项处理,那么 WordPress 具体是怎么管理全局选项的呢?

WordPress 全局选项管理的接口叫做 Option API,它是一种简单且标准化的在数据库中存储数据的方法,它使用给定的自定义名称将数据存储到 wp_options 表中。

WordPress 提供了 Option 的增删查改四个操作的函数,如果你安装的 WordPress 是多站点版本,那么还有对应的 _site_ 函数应用全网选项的函数,同样使用给定的自定义名称将数据存储到 wp_sitemeta 表中。

但是多站点的选项设置用到场景比较少,所以今天我们还是详细介绍一下 Option 的增删查改四个操作的函数:

增加选项|add_option

add_option( string $option, mixed $value = '', string $deprecated = '', string|bool $autoload = null ): bool

add_option 函数实现给 WordPress 增加一个选项,选项的名称通过参数 $option 指定,选项的值 $value 支持标量和非标量,如果非标量的话,则该值可以被序列化,但是无需手动对值进行序列化,该函数会在将值插入数据库之前会进行序列化操作,所以简单说,就是把各种类型值 $value 无需做任何处理,以 $option 作为名称添加到选项中。

另外第三个参数是被放弃的,不用管,如果要用到第四个参数 $autoload 的时候,三个参数的位置直接输入空字符串即可,这里简单说下一下第四个参数 $autoload,用于定义在 WordPress 启动的时候是否自动加载该选项到内存中,该参数默认值为 null,意思是它会自动根据 $value 大小来决定是否自动加载,小于 150000 字节则会自动加载,如果不管大小都要求自动加载,则可以将其设置 'on',无需自动加载,则需要将其设置为 'off'

最后如果该选项如果被成功添加,则返回 true,否则 false,额外说一下如果该选项数据库已有,则无法添加成功,如果你是想如已存在则修改,则建议用到后面介绍 update_option 函数。

add_option( 'my_option', 'my_value' );

比如上面代码就添加一个名称为 'my_option' 选项,它的值为:'my_value'

删除选项|delete_option

delete_option( string $option ): bool

delete_option 函数删除名称为 $option 的选项,删除选项函数比较简单,比如下面的代码就是删除名称为 'my_option' 选项。

delete_option( 'my_option' );

查询选项|get_option

get_option( string $option, mixed $default_value = false ): mixed

get_option 函数用于获取名称为 $option 的选项的值,除该参数之外,它还有第二个参数 $default_value,该参数默认值为 false,如果选项不存在,则返回该值。

get_option 函数返回值的类型可能会因与保存或更新选项时传递的类型不同而不同,如果选项值被序列化了,那么在返回时它将被反序列化,在这种情况下,返回的类型将会相同,比如存储一个如数组这样的非标量值,将返回相同的数组。

在大多数情况下,非字符串的标量和 null 值存储被转换并返回为字符串等效值。比如通过 add_option( 'my_option', $value ) 添加选项,然后通过 get_option( 'my_option' ) 获取选项值将会:

  • false 返回 string(0) ""
  • true 返回 string(1) "1"
  • 0 返回 string(1) "0"
  • 1 返回 string(1) "1"
  • '0' 返回 string(1) "0"
  • '1' 返回 string(1) "1"
  • null 返回 string(0) ""

如果添加是非标量的值,比如 add_option( 'my_array', array( false, 'str', null ) ), 返回的值将与原始值完全相同,因为它在保存到数据库之前已经被序列化了:

array(3) {
    [0] => bool(false)
    [1] => string(3) "str"
    [2] => NULL
}

更新选项|update_option

update_option( string $option, mixed $value, string|bool $autoload = null ): bool

update_option 函数的参数和 add_option 函数参数除了没有放弃的参数,基本都是一致的,用法也是一样的,这里就不重复了。

那么 update_option 函数和 add_option 函数的区别主要是:add_option 函数只会添加,如果已经存在,则不会覆盖,而 update_option 函数则会修改现有的选项,如果不存在,它则会调用 add_option 函数增加。

update_option( 'my_option', 'my_value' );

比如上面代码就修改名称为 'my_option' 选项的值为 'my_value',如果不存在则增加该选项,值也是为 'my_value'。

总结

关于 WordPress 全局选项,或者说站点选项的开发接口介绍,最核心的部分就是这四个函数,只要认真阅读这篇文章,那么进行开发的时候基本不会有太大的问题。

❌
❌