剖析 `WP_Post` 类的源码,它是如何通过 `__construct()` 方法从数据库行中实例化一个文章对象的?

各位老铁,早上好啊!今天咱就来聊聊 WordPress 里面的 WP_Post 类,一个承载着文章灵魂的家伙。特别是它那至关重要的构造函数 __construct(),看看它是怎么把数据库里冷冰冰的数据变成活生生的文章对象的。

开场白:WP_Post 是个啥?

首先,WP_Post 类是 WordPress 用来表示一篇文章(post)的对象。它封装了文章的所有属性,比如标题、内容、作者、发布时间等等。我们平时在 WordPress 后台看到的文章,在代码里其实都是 WP_Post 类的实例。

__construct():文章对象的“诞生”

__construct() 方法,也就是构造函数,是类里面的一个特殊方法。当你使用 new WP_Post() 创建一个对象时,这个方法就会自动执行。它的主要任务就是初始化对象,给对象的各个属性赋值。

WP_Post 类里,__construct() 方法接收一个参数:$post。这个 $post 可以是一个文章 ID(整数),也可以是一个包含文章数据的对象(比如从数据库查询出来的 stdClass 对象)。

源码剖析:从 ID 到对象

先来看看当 $post 是一个文章 ID 的时候,__construct() 做了什么:

/**
 * WordPress Post class.
 *
 * @since 2.3.0
 */
class WP_Post {

    /**
     * Post ID.
     *
     * @since 4.4.0
     * @var int
     */
    public $ID = 0;

    /**
     * Constructor.
     *
     * @param WP_Post|stdClass|int $post Post object or ID.
     */
    public function __construct( $post = null ) {
        if ( is_numeric( $post ) ) {
            $post = get_post( $post );
        }

        if ( isset( $post ) && is_object( $post ) ) {
            foreach ( get_object_vars( $post ) as $key => $value ) {
                $this->$key = $value;
            }

            /**
             * Fires after the WordPress Post object is set up.
             *
             * @since 2.3.0
             *
             * @param WP_Post $this Post object.
             */
            do_action( 'wp_post_construct', $this );
        }
    }
}
  1. 类型检查: if ( is_numeric( $post ) ) 这一行判断 $post 是不是一个数字。如果是,说明它是一个文章 ID。
  2. 获取文章数据: 如果 $post 是 ID,那么 get_post( $post ) 函数就会被调用。get_post() 函数会根据这个 ID 去数据库里查询文章数据,并返回一个包含文章数据的对象(通常是 stdClass 对象)。
  3. 对象赋值: if ( isset( $post ) && is_object( $post ) ) 检查 $post 是否被设置并且是一个对象。如果是,就用 foreach 循环遍历 $post 对象的所有属性,然后把这些属性的值赋给当前 WP_Post 对象的对应属性。 这一步是把数据库里取出来的数据填充到 WP_Post 对象的关键步骤。
  4. 触发钩子: do_action( 'wp_post_construct', $this ); 这一行触发了一个名为 wp_post_construct 的 action 钩子。 这允许其他插件或主题在 WP_Post 对象创建之后执行一些自定义操作。

源码剖析:从对象到对象

如果 $post 本身就是一个包含文章数据的对象(比如 stdClass),那么 __construct() 就不会再去数据库查询,而是直接把 $post 对象的属性赋值给当前 WP_Post 对象。

    public function __construct( $post = null ) {
        if ( is_numeric( $post ) ) {
            $post = get_post( $post );
        }

        if ( isset( $post ) && is_object( $post ) ) {
            foreach ( get_object_vars( $post ) as $key => $value ) {
                $this->$key = $value;
            }

            /**
             * Fires after the WordPress Post object is set up.
             *
             * @since 2.3.0
             *
             * @param WP_Post $this Post object.
             */
            do_action( 'wp_post_construct', $this );
        }
    }

这段代码和上面基本一样,只是跳过了 get_post() 那一步,直接进入了对象赋值的环节。

例子:实战演练

为了更好地理解,咱们来写几个例子:

例子 1:通过 ID 创建 WP_Post 对象

$post_id = 123; // 假设文章 ID 是 123
$my_post = new WP_Post( $post_id );

// 现在 $my_post 就是一个 WP_Post 对象,包含了 ID 为 123 的文章的所有数据
echo $my_post->post_title; // 输出文章标题
echo $my_post->post_content; // 输出文章内容

在这个例子中,我们先定义了一个文章 ID,然后用这个 ID 创建了一个 WP_Post 对象。__construct() 方法会自动调用 get_post() 函数去数据库查询文章数据,并把数据赋值给 $my_post 对象的各个属性。

例子 2:通过 stdClass 对象创建 WP_Post 对象

global $wpdb;
$post_id = 123;
$post_data = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->posts} WHERE ID = %d", $post_id ) );

$my_post = new WP_Post( $post_data );

// 现在 $my_post 就是一个 WP_Post 对象,包含了 ID 为 123 的文章的所有数据
echo $my_post->post_title; // 输出文章标题
echo $my_post->post_content; // 输出文章内容

在这个例子中,我们先用 $wpdb 对象直接从数据库里查询文章数据,得到一个 stdClass 对象 $post_data。然后,我们把 $post_data 传给 WP_Post 的构造函数。__construct() 方法会直接把 $post_data 对象的属性赋值给 $my_post 对象的属性。

属性列表:WP_Post 对象都有些啥?

一个 WP_Post 对象包含了很多属性,这些属性对应着文章的各种信息。下面列出一些常用的属性:

属性名 数据类型 描述
ID int 文章 ID
post_author string 文章作者 ID
post_date string 文章发布时间(YYYY-MM-DD HH:MM:SS)
post_date_gmt string 文章发布时间(GMT)
post_content string 文章内容
post_title string 文章标题
post_excerpt string 文章摘要
post_status string 文章状态(publish, draft, pending 等)
comment_status string 评论状态(open, closed)
ping_status string Pingback/Trackback 状态(open, closed)
post_password string 文章密码
post_name string 文章别名(slug)
to_ping string 需要 Pingback 的 URL 列表
pinged string 已经 Pingback 的 URL 列表
post_modified string 文章最后修改时间(YYYY-MM-DD HH:MM:SS)
post_modified_gmt string 文章最后修改时间(GMT)
post_content_filtered string 过滤后的文章内容
post_parent int 父文章 ID(用于页面)
guid string 文章的 GUID(全局唯一标识符)
menu_order int 菜单排序
post_type string 文章类型(post, page, attachment 等)
post_mime_type string 文章 MIME 类型(用于附件)
comment_count string 评论数量
filter string 数据过滤类型

wp_post_construct 钩子:锦上添花

do_action( 'wp_post_construct', $this ); 这行代码触发了一个 action 钩子。这意味着你可以在 WP_Post 对象创建之后,做一些自定义的操作。比如,你可以添加一些自定义的属性,或者修改已有的属性。

add_action( 'wp_post_construct', 'my_custom_post_setup' );

function my_custom_post_setup( $post ) {
    // 检查是否是特定类型的文章
    if ( $post->post_type == 'my_custom_post_type' ) {
        // 添加一个自定义属性
        $post->my_custom_field = get_post_meta( $post->ID, 'my_custom_field', true );
    }
}

在这个例子中,我们定义了一个名为 my_custom_post_setup 的函数,这个函数会在 WP_Post 对象创建之后被调用。我们在这个函数里检查文章类型是否是 my_custom_post_type,如果是,就从文章的 meta 数据里获取一个名为 my_custom_field 的自定义字段,并把它的值赋给 WP_Post 对象的 my_custom_field 属性。

总结:__construct() 的奥秘

WP_Post 类的 __construct() 方法是一个非常重要的函数。它负责把数据库里的文章数据转换成一个可用的 WP_Post 对象。 无论是通过文章 ID 还是通过现有的对象,__construct() 都能完成这个任务。 通过理解 __construct() 方法的工作原理,我们可以更好地理解 WordPress 的文章对象模型,并在开发中灵活运用。

希望今天的讲解能帮助大家更深入地理解 WP_Post 类的 __construct() 方法。记住,理解源码是成为 WordPress 大神的必经之路!下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注