大家好,欢迎来到今天的“解剖WordPress”系列讲座!今天我们要深入探讨WordPress世界中一个至关重要的角色——WP_Term
类。别害怕,虽然名字听起来有点技术范儿,但其实它就像一个勤劳的图书管理员,负责管理和提供我们网站上的各种“标签”和“分类”。
好,让我们开始吧!
WP_Term
:术语数据的“容器”
首先,我们需要明确一点:在WordPress中,分类法(Taxonomies)是组织内容的一种方式。常见的分类法包括类别(Categories)和标签(Tags)。而术语(Terms)则是分类法下的具体值。例如,“科技”是一个类别,“WordPress”是一个标签。
WP_Term
类就是用来封装这些术语的数据的。它就像一个容器,把一个术语的所有信息都装进去,方便我们访问和操作。
源码探索:从构造函数开始
我们先来看看 WP_Term
类的构造函数,这通常是了解一个类如何工作的第一步。
/**
* WP_Term class.
*
* @since 4.4.0
*/
class WP_Term {
/**
* Term ID.
*
* @since 4.4.0
* @access public
* @var int
*/
public $term_id;
/**
* Term name.
*
* @since 4.4.0
* @access public
* @var string
*/
public $name;
/**
* Term slug.
*
* @since 4.4.0
* @access public
* @var string
*/
public $slug;
/**
* Term group.
*
* @since 4.4.0
* @access public
* @var int
*/
public $term_group;
/**
* Term taxonomy ID.
*
* @since 4.4.0
* @access public
* @var int
*/
public $term_taxonomy_id;
/**
* Taxonomy name.
*
* @since 4.4.0
* @access public
* @var string
*/
public $taxonomy;
/**
* Term description.
*
* @since 4.4.0
* @access public
* @var string
*/
public $description;
/**
* Term parent ID.
*
* @since 4.4.0
* @access public
* @var int
*/
public $parent;
/**
* Term count.
*
* @since 4.4.0
* @access public
* @var int
*/
public $count;
/**
* Object cache group.
*
* @since 4.4.0
* @access public
* @var string
*/
public $filter = 'raw';
/**
* Constructor.
*
* @since 4.4.0
*
* @param WP_Term|object|int|null $term Term to initialise the WP_Term object with.
*/
public function __construct( $term ) {
if ( is_a( $term, 'WP_Term' ) ) {
$this->init( $term->to_array() );
return;
}
if ( is_object( $term ) || is_array( $term ) ) {
$this->init( $term );
return;
}
if ( is_numeric( $term ) ) {
$term = get_term( (int) $term );
if ( $term ) {
$this->init( $term );
}
}
}
/**
* Initialises term properties.
*
* @since 4.4.0
* @access protected
*
* @param WP_Term|object|array $term Term to initialise the WP_Term object with.
*/
protected function init( $term ) {
foreach ( get_object_vars( $this ) as $key => $value ) {
if ( isset( $term->$key ) ) {
$this->$key = $term->$key;
} elseif ( isset( $term[ $key ] ) ) {
$this->$key = $term[ $key ];
}
}
$this->filter = 'raw';
}
/**
* Sanitizes term fields.
*
* @since 4.4.0
* @access public
*/
public function sanitize() {
$this->name = sanitize_term_field( 'name', $this->name, $this->term_id, $this->taxonomy, 'raw' );
$this->slug = sanitize_term_field( 'slug', $this->slug, $this->term_id, $this->taxonomy, 'raw' );
$this->description = sanitize_term_field( 'description', $this->description, $this->term_id, $this->taxonomy, 'raw' );
$this->filter = 'display';
}
/**
* Returns the term as an array.
*
* @since 4.4.0
* @access public
*
* @return array Term as an array.
*/
public function to_array() {
$term = get_object_vars( $this );
unset( $term['filter'] );
return $term;
}
/**
* __get magic method.
*
* @since 4.4.0
* @access public
*
* @param string $key Key to get.
* @return mixed Maybe filtered term field.
*/
public function __get( $key ) {
if ( 'filter' === $key ) {
return $this->filter;
}
if ( in_array( $key, array( 'name', 'slug', 'description' ), true ) ) {
return sanitize_term_field( $key, $this->$key, $this->term_id, $this->taxonomy, $this->filter );
}
return $this->$key;
}
/**
* __isset magic method.
*
* @since 4.4.0
* @access public
*
* @param string $key Key to check.
* @return bool Whether the key exists.
*/
public function __isset( $key ) {
if ( 'filter' === $key ) {
return true;
}
return isset( $this->$key );
}
}
让我们分解一下:
-
属性(Public Properties):
$term_id
: 术语的ID,就像图书的唯一编号。$name
: 术语的名称,例如“科技”或“WordPress”。$slug
: 术语的别名,通常用于URL中,例如“technology”或“wordpress”。$term_group
: 术语组,通常不用。$term_taxonomy_id
: 术语分类ID,关联术语和分类法。$taxonomy
: 分类法的名称,例如“category”或“post_tag”。$description
: 术语的描述,就像图书的简介。$parent
: 父级术语的ID,用于层级分类法。$count
: 使用该术语的文章数量,就像图书的借阅次数。$filter
: 控制如何过滤术语的字段,默认为raw
。
-
构造函数
__construct()
: 这个函数负责初始化WP_Term
对象。它可以接受一个WP_Term
对象、一个对象、一个数组或一个术语ID作为参数。它会根据传入的参数类型,调用init()
方法来填充对象的属性。 -
初始化方法
init()
: 这个方法接受一个数组或对象,然后遍历WP_Term
类的所有属性,如果传入的数组或对象中存在相应的键或属性,就将它们的值赋给WP_Term
对象的属性。
例子:创建一个 WP_Term
对象
假设我们有一个术语,它的ID是 123,名称是 "JavaScript",Slug 是 "javascript", Taxonomy 是 "category"。我们可以这样创建一个 WP_Term
对象:
$term_data = (object) array(
'term_id' => 123,
'name' => 'JavaScript',
'slug' => 'javascript',
'taxonomy' => 'category'
);
$term = new WP_Term( $term_data );
echo $term->name; // 输出:JavaScript
echo $term->term_id; // 输出:123
或者,如果已经有了一个术语ID,可以直接这样创建:
$term_id = 123;
$term = new WP_Term( $term_id );
if ($term && !is_wp_error($term)) {
echo $term->name; // 输出:JavaScript
echo $term->term_id; // 输出:123
} else {
echo "Term not found or an error occurred.";
}
属性访问:直接访问与 __get()
方法
一旦我们创建了 WP_Term
对象,就可以直接访问它的属性,例如 $term->name
、$term->slug
等。
但是,WP_Term
类还使用了一个魔术方法 __get()
,它会在我们尝试访问不存在的属性时被调用。在这个方法中,WordPress会对某些属性(如 name
、slug
和 description
)进行过滤,以确保输出的内容是安全的。
public function __get( $key ) {
if ( 'filter' === $key ) {
return $this->filter;
}
if ( in_array( $key, array( 'name', 'slug', 'description' ), true ) ) {
return sanitize_term_field( $key, $this->$key, $this->term_id, $this->taxonomy, $this->filter );
}
return $this->$key;
}
这里的 sanitize_term_field()
函数非常重要,它负责对术语的字段进行清理和过滤,以防止XSS攻击。$this->filter
变量决定了过滤的级别。默认情况下,$filter
的值为 raw
,表示不进行任何过滤。但是,当我们调用 sanitize()
方法时,$filter
的值会被设置为 display
,表示进行显示级别的过滤。
sanitize()
方法:安全卫士
sanitize()
方法用于清理和过滤术语的字段,以确保它们是安全的。
public function sanitize() {
$this->name = sanitize_term_field( 'name', $this->name, $this->term_id, $this->taxonomy, 'raw' );
$this->slug = sanitize_term_field( 'slug', $this->slug, $this->term_id, $this->taxonomy, 'raw' );
$this->description = sanitize_term_field( 'description', $this->description, $this->term_id, $this->taxonomy, 'raw' );
$this->filter = 'display';
}
这个方法会调用 sanitize_term_field()
函数,对 name
、slug
和 description
字段进行清理和过滤。同时,它还会将 $filter
的值设置为 display
,以便在后续访问这些字段时,进行显示级别的过滤。
to_array()
方法:转换为数组
to_array()
方法用于将 WP_Term
对象转换为数组。
public function to_array() {
$term = get_object_vars( $this );
unset( $term['filter'] );
return $term;
}
这个方法会使用 get_object_vars()
函数获取 WP_Term
对象的所有属性,并将它们转换为一个数组。然后,它会从数组中移除 filter
属性,并返回最终的数组。
__isset()
方法:检查属性是否存在
__isset()
方法是一个魔术方法,用于检查一个属性是否存在。
public function __isset( $key ) {
if ( 'filter' === $key ) {
return true;
}
return isset( $this->$key );
}
这个方法会检查 $key
是否为 filter
。如果是,则返回 true
。否则,它会使用 isset()
函数检查 $this->$key
是否存在,并返回结果。
实际应用:获取分类术语信息
现在,让我们看看如何在实际应用中使用 WP_Term
类。假设我们要获取ID为 5 的分类术语的信息:
$term = get_term( 5, 'category' );
if ( $term && ! is_wp_error( $term ) ) {
echo 'Term ID: ' . $term->term_id . '<br>';
echo 'Term Name: ' . $term->name . '<br>';
echo 'Term Slug: ' . $term->slug . '<br>';
echo 'Term Description: ' . $term->description . '<br>';
echo 'Term Link: ' . get_term_link( $term ) . '<br>';
} else {
echo 'Term not found!';
}
在这个例子中,我们首先使用 get_term()
函数获取ID为 5 的分类术语。get_term()
函数会返回一个 WP_Term
对象。然后,我们可以直接访问 WP_Term
对象的属性,例如 term_id
、name
、slug
和 description
。
总结:WP_Term
的核心作用
总而言之,WP_Term
类在 WordPress 中扮演着以下核心角色:
- 封装术语数据: 它将术语的所有信息(ID、名称、别名、描述等)封装在一个对象中,方便我们访问和操作。
- 提供属性访问: 我们可以直接访问
WP_Term
对象的属性,获取术语的信息。 - 进行数据过滤: 通过
__get()
方法和sanitize_term_field()
函数,WP_Term
类可以对术语的字段进行过滤,以确保输出的内容是安全的。 - 转换为数组: 通过
to_array()
方法,我们可以将WP_Term
对象转换为数组,方便进行数据处理。
表格总结
属性/方法 | 描述 |
---|---|
$term_id |
术语的ID。 |
$name |
术语的名称。 |
$slug |
术语的别名。 |
$taxonomy |
分类法的名称。 |
$description |
术语的描述。 |
__construct() |
构造函数,用于创建 WP_Term 对象。 |
init() |
初始化方法,用于填充 WP_Term 对象的属性。 |
sanitize() |
清理和过滤术语的字段,以确保它们是安全的。 |
to_array() |
将 WP_Term 对象转换为数组。 |
__get() |
魔术方法,在访问不存在的属性时被调用,用于对某些属性进行过滤。 |
__isset() |
魔术方法,用于检查一个属性是否存在。 |
补充说明:对象缓存
值得一提的是,WordPress 使用对象缓存来提高性能。当我们第一次获取一个术语时,WordPress 会将 WP_Term
对象存储在对象缓存中。当我们再次获取同一个术语时,WordPress 会直接从对象缓存中获取,而无需再次查询数据库。这可以显著提高网站的性能。
WP_Term
类本身不直接处理对象缓存,而是依赖于 WordPress 的核心函数,例如 get_term()
。get_term()
函数会负责从对象缓存中获取术语,或者在对象缓存中不存在时,从数据库中获取并存储到对象缓存中。
总结
WP_Term
类是 WordPress 中一个重要的类,它负责封装和管理分类术语的数据。通过了解 WP_Term
类的源码,我们可以更好地理解 WordPress 的工作原理,并能够更有效地开发 WordPress 插件和主题。
希望今天的讲座对你有所帮助!下次再见!