解析 WordPress `get_children()` 函数的源码:如何通过 `WP_Query` 查询文章的子文章或附件。

大家好,我是你们今天的WordPress源码解剖师,代号“探针”,今天咱们要聊聊WordPress里一个挺常用的函数——get_children()。 别看它名字简单,肚子里可有不少弯弯绕绕。 咱们的任务就是把它扒个精光,看看它是怎么通过WP_Query这把瑞士军刀,来找到文章的子文章或者附件的。准备好了吗?开始解剖!

第一步:认识get_children()——这孩子是干啥的?

简单来说,get_children()函数的作用就是:获取指定文章的子文章或者附件。 这里的“子文章”指的是那些post_parent字段指向指定文章ID的文章。 附件嘛,自然就是那些与文章关联的图片、文档之类的媒体文件。

它的函数原型长这样:

<?php
get_children( string|array $args = '', string $output = OBJECT );
?>
  • $args: 是一个数组或者查询字符串,用来传递各种参数,比如排序方式、文章类型等等。
  • $output: 指定返回的数据类型,默认是OBJECT,也就是返回文章对象的数组。还可以是ARRAY_A(关联数组)、ARRAY_N(索引数组)或者OBJECT_K(以文章ID为键名的对象数组)。

第二步:进入源码——get_children()的内心世界

别怕,源码没那么可怕。我们先从wp-includes/post.php这个文件里找到get_children()的真身。

function get_children( $args = '', $output = OBJECT ) {
    $defaults = array(
        'numberposts' => -1,
        'post_status' => 'any',
        'post_type' => 'any',
        'post_parent' => 0,
        'orderby' => 'menu_order ASC, post_title ASC',
        'order' => 'ASC',
        'offset' => 0,
    );

    $r = wp_parse_args( $args, $defaults );

    $children = get_posts( $r );

    if ( ! $children ) {
        return array();
    }

    if ( OBJECT == $output ) {
        return $children;
    }

    $retval = array();

    if ( ARRAY_A == $output ) {
        foreach ( (array) $children as $child ) {
            $retval[ $child->ID ] = get_object_vars( $child );
        }
    } elseif ( ARRAY_N == $output ) {
        foreach ( (array) $children as $child ) {
            $retval[ $child->ID ] = array_values( get_object_vars( $child ) );
        }
    } elseif ( OBJECT_K == $output ) {
        foreach ( (array) $children as $child ) {
            $retval[ $child->ID ] = $child;
        }
    }

    return $retval;
}

看完这段代码,是不是感觉豁然开朗? 别急,我来给你细细分解:

  1. 默认参数:

    函数一开始定义了一堆默认参数,放在$defaults数组里。 这些参数控制着查询的行为,比如:

    • numberposts: 要获取的文章数量,-1表示获取所有。
    • post_status: 文章状态,any表示任何状态的文章都获取。
    • post_type: 文章类型,any表示任何文章类型都获取。
    • post_parent这个最重要! 它指定了父文章的ID,也就是我们要找的子文章的post_parent字段要等于这个值。 默认值是0,也就是根文章,没有父文章的文章。
    • orderby: 排序方式,默认是按照menu_order(菜单顺序)和post_title(文章标题)排序。
    • order: 排序方向,默认是升序ASC
    • offset: 偏移量,从第几篇文章开始获取。

    这些参数给了我们很大的灵活性,可以根据需要定制查询。

  2. 参数合并:

    $r = wp_parse_args( $args, $defaults ); 这行代码把我们传入的参数$args和默认参数$defaults合并起来。 如果我们在$args里指定了某个参数,比如'post_type' => 'attachment', 那么就会覆盖默认值'post_type' => 'any'

  3. 核心查询:get_posts()

    $children = get_posts( $r ); 这行代码是整个函数的灵魂!它调用了get_posts()函数,并把合并后的参数$r传给它。

    等等,get_posts()又是何方神圣? 其实,get_posts()函数是基于WP_Query类的一个封装。 它接收一个参数数组,然后创建一个WP_Query对象,执行查询,并返回查询结果。 所以,get_posts()才是真正干活的人,而WP_Query是它背后的力量。

  4. 结果处理:

    如果get_posts()没有找到任何文章,那么$children就是一个空数组,函数直接返回一个空数组。

    如果找到了文章,那么就根据$output参数来决定返回的数据类型。 默认情况下,$outputOBJECT,也就是直接返回get_posts()返回的文章对象数组。

    如果$output是其他值,比如ARRAY_AARRAY_N或者OBJECT_K,那么就需要对文章对象数组进行转换,才能返回对应格式的数据。

第三步:WP_Query登场——幕后英雄

现在,让我们把聚光灯打到WP_Query身上。 我们要看看get_posts()函数是如何利用WP_Query来查询文章的。

虽然我们没有直接在get_children()函数里看到WP_Query的身影,但是get_posts()函数内部会创建一个WP_Query对象,并使用我们传递的参数来构建查询。

为了更清楚地理解这一点,我们可以简单模拟一下get_posts()函数内部的逻辑:

<?php
// 模拟 get_posts() 函数内部的逻辑
function my_get_posts( $args ) {
    $query = new WP_Query( $args ); // 创建 WP_Query 对象

    $posts = $query->posts; // 获取查询结果

    return $posts;
}

// 使用 my_get_posts() 函数来查询子文章
$args = array(
    'numberposts' => -1,
    'post_status' => 'any',
    'post_type' => 'any',
    'post_parent' => 123, // 假设我们要查询父文章ID为123的子文章
);

$children = my_get_posts( $args );

// 打印查询结果
if ( $children ) {
    foreach ( $children as $child ) {
        echo '子文章标题:' . $child->post_title . '<br>';
    }
} else {
    echo '没有找到子文章。';
}
?>

在这个例子中,我们创建了一个名为my_get_posts()的函数,它接收一个参数数组$args,然后创建一个WP_Query对象,并把$args传递给它。

WP_Query会根据$args里的参数来构建SQL查询语句,并从数据库中获取文章。

WP_Query对象有一个posts属性,它包含了查询结果,也就是文章对象数组。 我们只需要把这个posts属性返回,就可以得到查询结果了。

第四步:参数详解——玩转get_children()

现在,让我们来详细看看get_children()函数可以接收哪些参数,以及这些参数是如何影响WP_Query的查询行为的。

| 参数名 | 默认值 | 描述

发表回复

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