web-dev-qa-db-de.com

Unterschiedliche Postsortierreihenfolge in verschiedenen Kategorien

Ich muss each post eine unique post-Reihenfolge für mehrere Kategorien (pro Post) angeben. Ich kann mir eine Lösung mit benutzerdefinierten Feldern vorstellen, bei der für jede Kategorie eine entsprechende Benutzerdefinition vorhanden ist Feld für die Bestellung.

Z.B.

Kategorien: Playlist1 Playlist2 Playlist3

Benutzerdefinierte Felder für den Beitrag: Playlist1_Order Playlist2_Order Playlist3_Order

Diese Methode ist offensichtlich nicht leicht skalierbar, daher würde ich gerne wissen, ob jemand eine elegantere Lösung hat.

Hintergrund

Ich richte eine Site ein, die eine Rund-um-die-Uhr-Sendung begleitet. Die Wiedergabeliste für die Sendung ist eine 12-stündige Schleife, die einmal pro Woche geändert wird. Einige Shows werden hinzugefügt und entfernt und die Reihenfolge einiger Shows wird neu angeordnet. Ich beabsichtige, einen benutzerdefinierten Beitragstyp für Shows und eine benutzerdefinierte Taxonomie für Wiedergabelisten zu definieren. Jede Show wird zu einer oder mehreren Wiedergabelisten hinzugefügt. Es muss möglich sein, dass die Show in jeder Wiedergabeliste eine eindeutige Reihenfolge hat.

(Ich habe beschlossen, die Frage auf Posts und Kategorien zu beschränken, anstatt auf Post-Types und Taxonomien, um Verwirrung zu vermeiden.).

AKTUALISIEREN

Betrachten Sie zur Verdeutlichung dieses Beispiel. Es gibt einen Beitrag namens "Rods Radio Roundup". Es ist in den Kategorien "Tuesday Lineup" und "Wednesday Lineup". Am Dienstag ist es die dritte Show und am Mittwoch die 7. Show. Später verlässt es Mittwoch, wechselt aber am Donnerstag zum ersten und am Samstag zum fünften Platz. Und es gibt noch 40 andere Beiträge wie diesen.

Die entscheidende Frage: Wie können Sie mehrere Bestellungen für einen einzelnen Beitrag verwalten, eine pro Kategorie?

6
user6756

Ich habe diese Herausforderung kürzlich gemeistert. Wir brauchten eine Möglichkeit, eine unterschiedliche Sortierreihenfolge für jeden Beitrag in mehreren Kategorien zu speichern.

In der Tabelle wp_term_relationships befindet sich eine nicht verwendete Spalte, term_order, die standardmäßig den Wert 0 hat und bereits als Ganzzahl umgewandelt wurde.

Wenn einem Beitrag ein Begriff zugewiesen wird, erhält er für jeden zugewiesenen Begriff einen Eintrag in dieser Tabelle. Eine object_ID (post_ID), eine term_taxonomy_ID und die term order werden auf 0 gesetzt.

Herausforderungen:

  1. Die term_taxonomy_ID unterscheidet sich manchmal von der term_ID, sodass Sie Ihre term_taxonomy_IDs für jede Kategorie kennen müssen.

  2. Da der Standardwert immer 0 ist, benötigen Sie eine Methode, um diesen Wert zu erhöhen. Andernfalls stehen Ihre neuen Beiträge immer an erster Stelle.

    • Die einfache Möglichkeit besteht darin, den Datenbankstandard auf eine höhere Zahl zu ändern. Die andere Methode besteht darin, eine Funktion zu erstellen und an den Hook save_post, update_post oder draft_to_publish anzuhängen.
  3. Sie benötigen auch eine Möglichkeit, diese Posts abzufragen, da term_order nicht Teil der WP_Query-Klasse ist.

    • Verwenden Sie den Filter posts_where oder schreiben Sie eine benutzerdefinierte Abfragefunktion.
  4. Sie benötigen auch eine Möglichkeit, diese Beiträge zu sortieren. Ich werde die von mir verwendete Ajax-Drag & Drop-Methode skizzieren, aber Sie können auch eine Metabox oder ein benutzerdefiniertes Feld verwenden.

Ajax Drag & Drop Sortieren:

Sie müssen eine Seite mit Administratoroptionen erstellen und die Posts abfragen und in einer benutzerdefinierten Tabelle oder ungeordneten Liste ausgeben. Sie können dies auch mit Ajax ausführen, sodass der Benutzer lediglich eine Kategorie aus einem Auswahlfeld auswählen und dann die Beiträge aus dieser Kategorie laden muss. (Ich werde nur die Ajax- und Php-Funktionen bereitstellen, um die Bestellung zu speichern).

PHP wp_ajax Funktion:

add_action ( 'wp_ajax_item_sort', 'wnd_save_item_order' );
    function wnd_save_item_order () {
        global $wpdb;
        $wpdb->flush ();
        $posts = $_POST[ 'order' ];
        $str = str_replace ( "post-", "", $posts );
        $order = explode ( ',', $str );
        $cat_id = (int)$_POST[ 'cat' ];
        $counter = 1;
        foreach ( $order as $item_id ) {

            $wpdb->query ( "UPDATE $wpdb->term_relationships SET term_order = '$counter' WHERE object_id = '$item_id' AND term_taxonomy_id = '$cat_id'" );
            $counter++;
        }
         $response = '<div id="message" class="updated fade"> <p>Sort Order successfully updated</p></div>';
         echo $response;
         die( '<div id="message" class="updated fade"> <p>An error occured, order has not been saved.</p></div>' );
    }

Die jQuery Ajax:

// Add this to the admin_enque_scripts and do a $pagenow check.
function sort_order_js() { ?> 
  jQuery(document).ready(function($) {
     var catID = $("#cat-select option:selected").val()
      $("#" + catID + "-save-order").bind("click", function() {
      $("#" + catID + "-load-animation").show();

          $.post(ajaxurl, { action:'item_sort', cat: catID, pos: position, order: $("#" + catID + "-sortable").sortable('toArray').toString() },

          function(response) {
              $("#" + catID + "-update-response").text('Updated');
              $("#" + "-load-animation").hide();
               });
                return false;
            });

            <?php } ?>

Wie bekommen wir unsere neu bestellten Posts?

posts_orderby filter:

add_filter('posts_orderby', 'custom_posts_orderby');
function custom_posts_orderby($order) {
    $order_by = 'wp_term_relationships.term_order';
    $direction = 'DESC';
    $order = " ORDER BY $order_by $direction";
    return $order;
}

Benutzerdefinierte Abfrage-API

Sie können diese Funktion ausführen, indem Sie ein Array von Argumenten übergeben, das WP_Query ähnelt, und ein Array von post_ids zurückgeben

function custom_get_post_ids( $args ) {
        $defaults = array (
            'category_id'               => NULL,
            'exclude_array'             => array (),
            'post_status_array'         => array ( 'publish' ),
            'post_status'               => NULL,
            'post_type_array'           => array ( 'post' ),
            'post_type'                 => NULL,
            'offset'                    => 0,
            'length'                    => 7,
            'order_by'                  => 'wp_term_relationships.term_order',
            'order_direction'           => 'ASC',
            'secondary_order_by'        => 'post_date',
            'secondary_order_direction' => 'DESC',
        );

    $args = wp_parse_args( $args, $defaults );
    extract( $args, EXTR_SKIP );
    if ( isset( $post_type ) ) {
        $post_type_array = array ( $post_type );
    }
    // If the post_status passed to us is a string, convert it to an array
    if ( isset( $post_status ) ) {
        $post_status_array = array ( $post_status );
    }
    global $wpdb;
    $query = 'SELECT wp_posts.ID FROM wp_posts INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)';
    $query .= ' WHERE wp_term_relationships.term_taxonomy_id IN (' . intval( $category_id ) . ')';
    if ( count( $exclude_array ) > 0 ) {
        $exclude = implode( ',', $exclude_array );
        $query .= ' AND wp_posts.ID NOT IN (' . $exclude . ')';
    }
    $query .= " AND wp_posts.post_type IN('" . implode( "','", $post_type_array ) . "')";
    $query .= " AND wp_posts.post_status IN('" . implode( "','", $post_status_array ) . "')";
        $query .= " ORDER BY $order_by $order_direction";
    if ( ! empty( $secondary_order_by ) ) {
        $query .= ",$secondary_order_by $secondary_order_direction";
    }
    $query .= " LIMIT $offset, $length /*_get_post_ids() */";
    $num_results = $wpdb->query( $query );
    $res = array ();
    foreach ( $wpdb->last_result as $r ) {
        array_Push( $res, intval( $r->ID ) );
    }
    return ( $res );
    }

Schließlich müssen wir nur neue Posts festlegen, um eine term_taxonomy_id zu haben, die höher ist als die übliche Anzahl der zu bestellenden Posts.

function default_sort_order() {
    global $post, $wpdb;
    $categories = get_the_category( $post->ID);
    $id = $post->ID;
        foreach ( $categories as $cat ) {
            $cat_id = $cat->term_taxonomy_id;
            $wpdb->query ( "UPDATE $wpdb->term_relationships SET term_order = 20 WHERE object_id = '$id' AND term_taxonomy_id = '$cat_id'" );

        }
}

Immer noch hier?

Diese Methode wurde getestet und wird von einer großen Nachrichtenorganisation verwendet, um die Anzeigereihenfolge auf der Homepage und den Kategorieseiten festzulegen.

4
Chris_O

Dinge wie dieses werden sehr schnell komplex. Dies ist möglicherweise der Grund, warum das OP nie zurückgekehrt ist, da die Organisation von Live-Sendungen mit WP keine gute Idee ist (Anzeigeneinfügung, Rotationsregeln, Live-Änderungen im laufenden Betrieb usw.). Die meisten dieser Dinge lassen sich besser mit einer Anwendung erledigen, die über eine spezielle API verfügt, die auf diesen Anforderungen basiert, und über XML/JSON-Feeds, mit denen die Daten bei Bedarf ausgetauscht werden können (z. B. in WP).

Die Auftragserteilung
Diese Frage der Bestellung im Allgemeinen und der Drag & Drop-Bestellung scheint ein wunder Punkt zu sein, der in der Vergangenheit angesprochen wurde. Die meisten Mitglieder des Kernteams waren sich einig, dass WordPress chronologisch bleiben sollte. Alles andere sollte ein Plugin-Feature für Entwickler sein, das Problem ist, dass es eine Menge Leute gibt, die WordPress als Entwicklungsplattform verwenden, die darauf stoßen, WordPress ist ein CMS, richtig;)

Also, womit bleibt uns das übrig?

Drag & Drop ist sehr intuitiv, daher funktioniert die Verwendung von .sortable(); von jQuery UI mit einem benutzerdefinierten Datenbankeintrag oder einem Metafeld gut. Sie können so ziemlich das Gleiche tun wie im Standard-Post-Gallery-Editor (und im Menü-Editor), in dem Sie die Reihenfolge per Drag & Drop verschieben und manuell einen von Ihnen festgelegten Parameter für Anzahl und Sortierung (ASC, DESC) eingeben können könnte um den Namen oder einen beliebigen WP Query/WPDB-Parameter erweitert werden.

Alles, was komplexer wäre, müsste auf einem Abfrageregelsystem basieren, das den tatsächlichen Anforderungen entspricht.

Es gibt einige Plugins, die ich gesehen habe, wie PostMash und Orderly , aber nichts, von dem ich weiß, ist wirklich umfassend, so dass viele Vorlagendateien gehackt werden müssen.

1
Wyck

Ich weiß, dass Sie "Posts & Categories" gesagt haben, aber ich denke, Sie können Posts besser mit Posts verbinden und die Reihenfolge als Post-Metadaten speichern:

  • erstelle einen neuen Beitragstyp, show (empfohlen, aber du könntest stattdessen post verwenden)

  • erstelle einen neuen Beitragstyp, playlist (empfohlen, aber du könntest stattdessen post verwenden)

  • erstellen Sie eine Post/Playlist, Tuesday Lineup, und speichern Sie die Post-Metadaten shows = 8,73,5,68,994 (eine geordnete Liste der Show-IDs). (Das ACF Relationship Field fügt dazu eine great UI hinzu, aber das Prinzip ist dasselbe ohne sie.)

  • lesen Sie beim Anzeigen der einzelnen Beiträge/Wiedergabelisten den Wert für shows, rufen Sie diese Beiträge ab und zeigen Sie sie der Reihe nach an.

1
sam

Um dies in EXTREM Pseudo-Code zu tun, möchten Sie versuchen:

switch($cat_id) {
    case 1:
        $args = "sort rules for cat 1";
        break;
    case 2:
        $args= "sort rules for cat 2";
        break;
    etc...
    default:
        $args= "default sort rules";
        break;
}

$posts = get_posts($args);

Hinweis: Definieren Sie bei dieser Methode nur die "Ausnahmen" mit den case-Klauseln und die "Regel" mit der default.

0
Joshua

Einfach. PHP für und WordPress get_posts () und ein paar Checks reichen aus.

Sie können $args['orderby'] und $args['order'] ändern, um die Sortierung nach Bedarf vorzunehmen. Ansicht Bestellung & Bestellparameter

Nicht getestet, aber es sollte funktionieren!

function get_content($type, $categories){
    for($i = 0; $i < count($categories); $i++){
        // configure posts
        $args = array(
            'numberposts'     => -1,
            'offset'          => 0,
            'category_name'   => $categories[$i],
            'include'         => '',
            'exclude'         => '',
            'meta_key'        => '',
            'meta_value'      => '',
            'post_type'       => $type,
            'post_mime_type'  => '',
            'post_parent'     => '',
            'post_status'     => 'publish' 
        );
        // define different sorting methods depending on category
        if($categories[$i] == 'playlist-1'){
            $args['orderby'] = 'post_date';
            $args['order'] = 'DESC';
        } elseif($categories[$i] == 'playlist-2'){
            $args['orderby'] = 'post_date';
            $args['order'] = 'ASC';
        } elseif($categories[$i] == 'playlist-3'){
            $args['orderby'] = 'post_title';
            $args['order'] = 'ASC';
        } 
        // fetch the posts
        $postData[$categories[$i]] = get_posts($args);
    }
    return $postData;
}

// Choose the categories to sort
$categories = array('playlist-1', 'playlist-2', 'playlist-3');

// This will contain all categories and posts inside one array.
$allPosts = get_content('post', $categories);
//print_r($allPosts);

// EXAMPLE: To loop through a set of posts, you will need to access it like so
for($i = 0; $i < count($categories['playlist-1']); $i++){
    echo '<h1>'.$categories['playlist-1'][$i]['post_title'].'</h1>';
    echo apply_filter('the_content', $categories['playlist-1'][$i]['post_content']);
}

OR

GET POSTS BY TAXONOMY SORT ORDER

    function get_content_taxonomy($tax, $term){
        $wp_query = new WP_Query();
        $wp_query->query(array('posts_per_page' => -1, 'orderby' => 'title', 'order' => 'ASC', 'tax_query' => array(array('taxonomy' => $tax, 'field' => 'slug', 'terms' => $term))));
        $posts = $wp_query->posts;
        if(!empty($posts)){
            $return = $posts;
        }
        return $return;
    }

    // No idea how you have your stuff setup, but it could be like:
    $playlist1 = get_content_taxonomy('playlist', '1');
    // print_r($playlist1);
0
Michael Ecklund