it-swarm.com.de

Benutzerdefinierter Beitragstyp, WP_Query und 'orderby'

Ich habe einen benutzerdefinierten Beitragstyp mit folgendem Setup:

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

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

register_post_type('myType', $args);

Ich möchte alle Beiträge anzeigen und sortieren lassen wie im Bereich wp-admin (Einzug dient der Lesbarkeit):

1, 
2, 
3, 
   1, (parent 3)
   2, (parent 3)
4

Daher habe ich die folgende Abfrage mit dem Auftragstyp 'menu_order' versucht:

$loop = new WP_Query( array(
       'post_type' => 'myType'
     , 'posts_per_page' => 50
     , 'orderby' => 'menu_order'
     , 'order' => 'ASC'
));

Leider werden alle Posts nach menu_order sortiert, jedoch ausschließlich nach menu_order, wobei die übergeordnete Beziehung (post_parent-Attribut) ignoriert wird. Also bekomme ich so etwas

1,
1, (parent 3)
2, 
2, (parent 3)
3,
4

Das Ändern der Abfrage in 'orderby' => 'parent menu_order' führt zu folgenden Ergebnissen

1,
2, 
3,
4
1, (parent 3)
2, (parent 3)

Alles in allem sieht es für mich so aus, als würde alles wie geplant funktionieren und der orderby-Wert direkt in die entsprechende SQL-Anweisung 'Order By' übersetzt.

Frage

Was ist der einfachste Weg, um die gewünschte Bestellung zu erhalten?

SQL

Ich gehe davon aus, dass dies die wichtigste SQL-Abfrage ist, die WordPress erstellt:

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

was dann gefolgt wird mit:

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)

Workaround

Eine bekannte Problemumgehung, aber keine Antwort, besteht darin, allen Posts höhere und "beabstandete" Ordnungswerte zuzuweisen, wie z

100,
200, 
300,
   310,
   320,
400
4
SunnyRed

Soweit ich das beurteilen kann, gibt es auf Datenbankebene keine Umgehung. Dies ist ein Problem, auf das ich häufig stoße. In diesem Fall müssen Sie eine Liste mit Strukturreferenzen in ein geordnetes Array mit untergeordneten Elementen umwandeln, die unmittelbar nach den übergeordneten Elementen angezeigt werden. Dies kann in PHP erreicht werden, aber obwohl diese Lösung ziemlich kompakt ist, ist sie nicht besonders einfach.

Die folgende Lösung fügt dem Filter the_posts einen Filter hinzu, der die Ergebnismenge mit einer rekursiven Funktion strukturiert und dann abflacht.

// 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 );

Ich habe diese Lösung getestet und sie ist allgemein genug für beliebige Seitenhierarchien.

Dieser Code setzt voraus, dass die Posts bereits nach menu_order sortiert sind. Wenn Sie diese Lösung verwenden möchten, müssen Sie den Parameter orderby in "menu_order" ändern, in dem Sie new WP_Query aufrufen.

5
Bendoh

Weitere Optionen finden Sie im Codex , aber es sieht so aus, als würden Sie in diesem Fall 'parent' als primäre Sortierung verwenden.

$loop = new WP_Query( array(
       'post_type' => 'myType'
     , 'posts_per_page' => 50
     , 'orderby' => 'parent menu_order'
     , 'order' => 'ASC'
));

Dies wird hauptsächlich nach Eltern sortiert, mit einer sekundären Sortierung der Menüreihenfolge. Dies sollte Ihnen das gewünschte Ergebnis bringen.

6
Eric Holmes