web-dev-qa-db-fra.com

Ordre de tri différent dans différentes catégories

J'ai besoin de donner each post a unique commande pour plusieurs catégories (par publication), il est po Je peux imaginer une solution utilisant des champs personnalisés dans lesquels pour chaque catégorie il y a un personnalisé correspondant champ pour la commande.

Par exemple.

Catégories: Playlist1 Playlist2 Playlist3

Champs personnalisés pour le message: Playlist1_Order Playlist2_Order Playlist3_Order

Évidemment, cette méthode n’est pas facilement évolutive, alors j'aimerais savoir si quelqu'un a une solution plus élégante.

Contexte

Je suis en train de créer un site pour accompagner une émission 24h/24 et 7j/7. La liste de lecture de l'émission est une boucle de 12 heures modifiée une fois par semaine. Certains spectacles sont ajoutés et supprimés et l'ordre de certains spectacles est réarrangé. J'ai l'intention de définir un type de publication personnalisé et une taxonomie personnalisée de la liste de lecture. Chaque émission sera ajoutée à une ou plusieurs listes de lecture. Il doit être possible pour le spectacle d'avoir un ordre unique dans chaque playlist.

(J'ai décidé de limiter la question aux articles et catégories plutôt qu'aux types d'articles et aux taxonomies afin d'éviter toute confusion).

METTRE À JOUR

Pour clarifier, considérons cet exemple. Il y a un article intitulé "Rod's Radio Roundup". C'est dans les catégories "Mardi Line" et "Mercredi". Mardi c'est le troisième spectacle et mercredi c'est le 7ème spectacle. Plus tard, il quittera mercredi mais passera à la 1ère place jeudi et à la 5ème place samedi. Et il y a 40 autres posts comme celui-ci.

La question essentielle: comment maintenir plusieurs commandes, une par catégorie, pour un seul poste?

6
user6756

J'ai récemment surmonté ce même défi. Nous avions besoin d'un moyen de sauvegarder un ordre de tri différent pour chaque article dans plusieurs catégories.

Il y a une colonne inutilisée dans la table wp_term_relationships, term_order, dont la valeur par défaut est 0 et qui est déjà convertie en entier.

Lorsqu'un terme est attribué à une publication, il reçoit une entrée dans cette table pour chaque terme attribué. Un object_ID (post_ID), un term_taxonomy_ID et le terme order sont définis sur 0.

Défis:

  1. Le term_taxonomy_ID est parfois différent du term_ID, vous devrez donc connaître vos term_taxonomy_ID pour chaque catégorie.

  2. Étant donné que la valeur par défaut est toujours 0, vous avez besoin d'une méthode pour définir un nombre plus élevé, sinon toutes vos nouvelles publications viendront toujours en premier.

    • Le moyen le plus simple est simplement de modifier les valeurs par défaut de la base de données. L'autre méthode consiste à créer une fonction et à l'attacher au hook save_post, update_post ou draft_to_publish.
  3. Vous aurez également besoin d'un moyen d'interroger ces publications, car term_order ne fait pas partie de la classe WP_Query.

    • Utilisez le filtre posts_where ou écrivez une fonction de requête personnalisée.
  4. Vous aurez également besoin d'un moyen de trier ces messages. Je vais décrire la méthode de glisser-déposer Ajax que j’ai utilisée, mais vous pouvez également utiliser un champ métabox ou personnalisé.

Ajax glisser-déposer:

Vous devrez créer une page d’options d’administrateur, interroger les publications et les exporter dans un tableau personnalisé ou une liste non ordonnée. Vous pouvez également exécuter cela en utilisant Ajax. Il suffit donc à l'utilisateur de sélectionner une catégorie dans une zone de sélection, puis de charger les publications de cette catégorie. (Je ne fournirai que les fonctions Ajax et Php pour sauvegarder la commande).

Fonction PHP wp_ajax:

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>' );
    }

Le 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 } ?>

Comment obtenons-nous nos messages nouvellement commandés?

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;
}

API de requête personnalisée

Vous pouvez exécuter cette fonction en lui passant un tableau d'arguments similaire à WP_Query et elle retournera un tableau de post_ids

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

Enfin, nous avons juste besoin de définir de nouveaux messages pour que term_taxonomy_id soit supérieur au nombre de messages à commander.

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'" );

        }
}

Toujours là?

Cette méthode a été testée et est utilisée par une grande société de presse pour définir l'ordre d'affichage sur la page d'accueil et les pages de catégorie.

4
Chris_O

Cela devient rapidement très complexe. C’est peut-être pour cette raison que le PO n’est jamais revenu, car organiser des émissions en direct à l’aide de WP n’est pas une bonne idée (insertion d’annonces, règles de rotation, modifications en direct, etc.). La plupart de ces tâches sont mieux gérées par une application disposant d'une API spécifique basée sur ces besoins et disposant de flux XML/JSON permettant de lancer les données si nécessaire (comme dans WP).

Le problème d'ordre
Cette question de la commande en général et de la commande par glisser-déposer semble être un point sensible soulevé dans le passé, la plupart des membres de l’équipe centrale convenant que WordPress doit rester chronologique. Tout le reste devrait être une fonctionnalité de plugin pour les développeurs, le problème est qu'il y a un lot des personnes utilisant WordPress comme plate-forme de développement qui se heurtent à cela, WordPress est un CMS, à droite;)

Alors qu'est-ce que cela nous laisse?

Le glisser-déposer est vraiment intuitif, donc utiliser quelque chose comme la fonction .sortable(); de jQuery UI avec une entrée de base de données personnalisée ou un champ méta fonctionne bien. Vous pouvez à peu près faire la même chose que l’éditeur de galerie de messages par défaut (et l’éditeur de menus), dans lequel vous avez la possibilité de faire glisser une commande et de saisir manuellement un nombre et un paramètre de tri (ASC, DESC) que vous souhaitez. pourrait s'étendre à inclure le nom, ou n'importe quel paramètre WP Query/WPDB.

Tout ce qui est plus complexe devrait reposer sur une sorte de système de règle de requête qui serait assez spécifique aux exigences actuelles.

Certains plugins que j'ai vus font cela, tels que PostMash et Orderly , mais rien que je sache ne soit vraiment complet, d'où la nécessité de pirater de nombreux fichiers modèles.

1
Wyck

Je sais que vous avez dit "publications et catégories", mais je pense que vous ferez mieux de relier les publications aux publications et de stocker la commande en tant que métadonnées de publication:

  • créer un nouveau type de message, show (recommandé, mais vous pouvez utiliser post à la place)

  • créer un nouveau type de message, playlist (recommandé, mais vous pouvez utiliser post à la place)

  • créer une publication/une liste de lecture, Manche mardi, et enregistrer les métadonnées de la publication shows = 8,73,5,68,994 (une liste ordonnée d'identifiants d'émission). (Le champ de relation ACF ajoute un great UI pour cela, mais le principe est le même sans cela.)

  • lors de l'affichage de chaque publication/liste de lecture, lisez la valeur de shows, récupérez ces publications et affichez-les dans l'ordre.

1
sam

Pour faire cela dans EXTREME code pseudo vous voulez vraiment essayer:

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

Remarque: avec cette méthode, définissez uniquement les "exceptions" avec les clauses case et la "règle" avec default.

0
Joshua

Simple. PHP pour et WordPress get_posts () et quelques vérifications feront l'affaire.

Vous pouvez modifier $args['orderby'] et $args['order'] pour trier la manière dont vous avez besoin de le faire. Afficher Order & Orderby Parameters

Je n'ai pas testé, mais ça devrait marcher!

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

OBTENIR DES POSTES PAR TAXONOMIE ORDRE DE TRI

    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