自定义发布类型、WP_QUERY和‘orderby’

时间:2012-08-30 作者:SunnyRed

我有一个自定义的帖子类型,设置如下:

$supports = array(
    \'title\'
    , \'editor\'
    , \'thumbnail\'
    , \'revisions\'
    , \'page-attributes\'
);

$args = array(
  \'hierarchical\' => true
  , \'supports\' => $supports
  [...]
);

register_post_type(\'myType\', $args);
我想显示所有帖子,并将它们像在wp管理区域一样进行排序(缩进是为了可读性):

1, 
2, 
3, 
   1, (parent 3)
   2, (parent 3)
4
因此,我尝试了以下订单类型设置为“menu\\u order”的查询:

$loop = new WP_Query( array(
       \'post_type\' => \'myType\'
     , \'posts_per_page\' => 50
     , \'orderby\' => \'menu_order\'
     , \'order\' => \'ASC\'
));
不幸的是,所有帖子都是按menu_order, 但是menu_order 独占,忽略父关系(post_parent 属性)。所以我得到了这样的东西

1,
1, (parent 3)
2, 
2, (parent 3)
3,
4
将查询更改为\'orderby\' => \'parent menu_order\' 导致以下情况

1,
2, 
3,
4
1, (parent 3)
2, (parent 3)
因此,在我看来,一切都按照设计进行,orderby值直接转换为相应的SQL“Order By”。

问题

获得所需订单的最简单方法是什么?

SQL我假设这是wordpress创建的主要SQL查询:

SELECT SQL_CALC_FOUND_ROWS wp_2_posts.ID 
FROM wp_2_posts 
WHERE 1=1 AND wp_2_posts.post_type = \'inhalt\' AND (wp_2_posts.post_status = \'publish\' OR wp_2_posts.post_status = \'private\') 
ORDER BY wp_2_posts.post_parent, wp_2_posts.menu_order ASC LIMIT 0, 50
然后,接下来是:

SELECT wp_2_posts.* 
FROM wp_2_posts 
WHERE ID IN (40,42,44,46,48,50,52,54,56,58,60,76,62,65,69,71,74)

SELECT post_id, meta_key, meta_value 
FROM wp_2_postmeta 
WHERE post_id IN (40,42,44,46,48,50,52,54,56,58,60,62,65,74,69,71,76)
一个已知的解决方法,但不是一个答案,就是给所有帖子提供更高和更“间隔”的顺序值,如

100,
200, 
300,
   310,
   320,
400

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

据我所知,在数据库级别没有解决这个问题的方法。这是我经常遇到的一个问题,在这种情况下,需要将包含结构引用的列表转换为一个有序数组,子元素紧跟在其父元素之后。这可以在PHP中完成,但虽然这个解决方案相当紧凑,但它并不是非常直接。

以下解决方案将过滤器添加到the_posts filter,它使用递归函数构造结果集,然后将其展平。

// Add each level\'s child posts to the result list, in order
function recursively_flatten_list( $list, &$result ) {
    foreach( $list as $node ) {
        $result[] = $node[\'post\'];
        if( isset( $node[\'children\'] ) )
            recursively_flatten_list( $node[\'children\'], $result );
    }
}

function my_sort_posts( $posts, $query ) {
    // Don\'t do outside admin. Only operate on main query. Only operate on queries for pages.
    if( is_admin() || !$query->is_main_query() || $query->get( \'post_type\' ) != \'page\' )
        return;

    $refs = $list = array();
    // Make heirarchical structure in one pass.
    // Thanks again, Nate Weiner:
    // http://blog.ideashower.com/post/15147134343/create-a-parent-child-array-structure-in-one-pass
    foreach( $posts as $post ) {
        $thisref = &$refs[$post->ID];

        $thisref[\'post\'] = $post;

        if( $post->post_parent == 0)
            $list[$post->ID] = &$thisref;
        else
            $refs[$post->post_parent][\'children\'][$post->ID] = &$thisref;
    }

    // Create single, sorted list
    $result = array();
    recursively_flatten_list( $list, $result );

    return $result;
}
add_filter( \'the_posts\', \'my_sort_posts\', 10, 2 );
我已经测试过这个解决方案,它对于任意页面层次结构来说已经足够通用了。

此代码假定帖子已经由menu_order. 如果要使用此解决方案,请确保更改orderby 参数设置为"menu_order" 你打电话到哪里new WP_Query.

SO网友:Eric Holmes

请参见codex 对于其他选项,但在本例中,您似乎希望使用“parent”作为主要排序。

$loop = new WP_Query( array(
       \'post_type\' => \'myType\'
     , \'posts_per_page\' => 50
     , \'orderby\' => \'parent menu_order\'
     , \'order\' => \'ASC\'
));
这将主要按父级排序,其次是菜单顺序排序。这会给你你想要的结果。

结束

相关推荐

Protect Uploads in Multisite

我正在使用WordPress multisite(3.3.1),并试图保护从某些博客上传的内容不被热链接和直接访问。这与How to Protect Uploads, if User is not Logged In?, 但我只想通过服务器上运行的脚本访问上传内容(即,只有服务器可以显示/提供上传服务),因此内容可以受到WordPress用户权限的保护。例如,我有一个名为40c的字段。jpg位于localhost/files/2011/07/40c。jpg;我想让文件显示出来only 在本地域上由HTML