查询中的Foreach中的查询(查询异常)

时间:2021-05-11 作者:Lorn Waterfield

我正在实现this list 目前我觉得我应该能够用foreach来完成,而不是对每一个单独的查询;“房屋”;(House是一个CPT,也被指定为usermeta),但我无法让它工作。

目前正在对每个房屋进行这些查询(手动写入每个新查询的“房屋”帖子ID):

$houseid = \'8490\'; //Manually changing this id each time, so I have the code below repeated a bunch...
 $connectors = get_users( array( 
  \'fields\' => \'ID\',
  \'meta_query\' => array(
   \'relation\' => \'OR\',
   \'house\' => array(
    \'key\' => \'house\',
    \'value\' => $houseid,
   ),
   \'leader_of_house\' => array(
    \'key\' => \'leader_of_house\',
    \'value\' => $houseid,
   ),
  )
 ) );
$connections = new WP_Query( array( \'post_type\' => \'connection\', \'posts_per_page\' => -1, \'author__in\' => $connectors ) );
$total = $connections->found_posts; if ( !empty ( $total ) ) { echo \'<span class="connector"><p>\' . get_the_title($houseid) . \' (\' . $connections->found_posts . \' connections)</p></span>\'; }
因此,我开始编写一个foreach来遍历我之前手动编写的房屋ID,但它不起作用(它只显示一个结果,这就是我正在编写此代码的页面的标题)。以下是我当前的尝试:

$the_query = new WP_Query( array( \'post_type\' => \'house\', \'posts_per_page\' => -1 ) );
$houses = $the_query->get_posts();
foreach( $posts as $post ) {
 $houseid = $post->ID;
 $connectors = get_users( array( 
  \'fields\' => \'ID\',
  \'meta_query\' => array(
   \'relation\' => \'OR\',
   \'house\' => array(
    \'key\' => \'house\',
    \'value\' => $houseid,
   ),
   \'leader_of_house\' => array(
    \'key\' => \'leader_of_house\',
    \'value\' => $houseid,
   ),
  ),
 ) );
 $connections = new WP_Query( array( \'post_type\' => \'connection\', \'posts_per_page\' => -1, \'author__in\' => $connectors ) );
 $total = $connections->found_posts; if ( !empty ( $total ) ) { echo \'<span class="connector"><p>\' . get_the_title($houseid) . \' (\' . $connections->found_posts . \' connections)</p></span>\'; }
}
谁能告诉我哪里出了问题?

目标是列出每个;“房屋”;然后统计出;“连接”;(也是一个CPT),作者分配给每所房子创建。就像记分牌一样。So房屋>;具有匹配元(房屋ID)的用户(>;这些用户创建的连接。

2 个回复
最合适的回答,由SO网友:Sally CJ 整理而成

Good for you that you\'ve corrected the $posts that was undefined, but then:

  1. There\'s no need to call $the_query->get_posts() because when WP_Query is instantiated with a non-empty query, e.g. new WP_Query( \'post_type=house\' ) (contains one query arg — post_type) as opposed to new WP_Query() (no query args specified), the get_posts() method in that class will automatically be called.

  2. If you were trying to get the posts that were already fetched by the specific query, then get_posts() is not actually for that purpose. On the contrary, it will re-parse the query args, apply various filters, etc. and then re-query the database for the posts matching the query args. ( So basically, the same query is gonna be duplicated and it\'s not good.. )

    So how can you get that already fetched posts?

    Easy: Use the $posts property, i.e. $the_query->posts in your case.

  3. Referring to your second query ($connections), if you just want to access the value of $found_posts, then you should just set the posts_per_page to 1 and not -1.

    ( As an aside, I\'ve been hoping WP_Query would implement something like fields=count so that we could easily get the total number of found posts in the database.. )

Now as for this (from your comment): how to sort the results by the number in $total, rather than echoing in your foreach, you can store the totals (and post IDs) in an array and then sort and echo them afterwards.

Here\'s an example where I store them in an array named $list and used usort() to sort them — by the $total value, or the house name (post title) if the total is equal:

$the_query = new WP_Query( array(
    \'post_type\'      => \'house\',
    // Note: Instead of -1, you should use a high number like 99999..
    \'posts_per_page\' => -1,
) );

// each item is: array( <total connections>, <post ID>, <post title> )
$list = array();

foreach ( $the_query->posts as $post ) {
    $connectors = get_users( array(
        \'fields\'     => \'ID\',
        \'meta_query\' => array(
            \'relation\' => \'OR\',
            array(
                \'key\'   => \'house\',
                \'value\' => $post->ID,
            ),
            array(
                \'key\'   => \'leader_of_house\',
                \'value\' => $post->ID,
            ),
        ),
    ) );

    if ( empty( $connectors ) ) {
        continue;
    }

    $connections = new WP_Query( array(
        \'post_type\'      => \'connection\',
        \'posts_per_page\' => 1,
        \'author__in\'     => $connectors,
    ) );

    if ( $connections->found_posts ) {
        $list[] = array( $connections->found_posts, $post->ID, $post->post_title );
    }
}

// Sort by the total connections, or the post title instead if the total is equal.
usort( $list, function ( $a, $b ) {
    return $a[0] === $b[0] ? strcasecmp( $a[2], $b[2] ) : $b[0] > $a[0];
} );

if ( ! empty( $list ) ) {
    echo \'<ul>\';
    foreach ( $list as $item ) {
        list ( $total, $post_id ) = $item;

        echo \'<li><span class="connector">\' . esc_html( get_the_title( $post_id ) ) .
            " ($total connections)</span></li>";
    }
    echo \'</ul>\';
}

And with that, the first three items in this list would be displayed in the following order — the first two items have 4 connections, so they are instead sorted alphabetically in ascending order: (In MySQL, this is equivalent to ORDER BY total DESC, LOWER( post_title ) ASC)

Chapman, Robinson & Moore House (4 connections)
Databasix House (4 connections)
Aston & James House (2 connections)

So is that how you wanted the list be sorted? :)

SO网友:Lorn Waterfield

啊,我做到了。在上面的示例中,我刚刚拼凑了一些标识符的名称。这适用于可能感兴趣的任何人:

$the_query = new WP_Query( array( \'post_type\' => \'house\', \'fields\' => \'ID\', \'posts_per_page\' => -1 ) );
$posts = $the_query->get_posts();
foreach( $posts as $post ) {
 $connectors = get_users( array( 
  \'fields\' => \'ID\',
  \'meta_query\' => array(
   \'relation\' => \'OR\',
   \'house\' => array(
    \'key\' => \'house\',
    \'value\' => $post->ID,
   ),
   \'leader_of_house\' => array(
    \'key\' => \'leader_of_house\',
    \'value\' => $post->ID,
   ),
  ),
 ) );
$connections = new WP_Query( array( \'post_type\' => \'connection\', \'posts_per_page\' => -1, \'author__in\' => $connectors ) );
$total = $connections->found_posts; if ( !empty ( $total ) ) { echo \'<span class="connector"><p>\' . get_the_title($post->ID) . \' (\' . $total . \' connections)</p></span>\'; }
}