web-dev-qa-db-fra.com

Afficher tous les articles de la catégorie, avec les articles tag en haut

Reformuler la question

Je dois commander des articles dans la boucle pour ma catégorie car. Ce dont j'ai besoin, si je visite la page catégorie de car, j'ai besoin que tous les messages marqués BMW soient affichés en premier, puis les autres messages non marqués du tag BMW.

Si mon posts_per_page est configuré pour afficher 10 posts et que je suis à la première page, et que trois des dix posts sont marqués BMW, ces trois posts doivent apparaître en premier et le reste suit ces trois posts. Lorsque je clique et que je passe à la page deux, il en va de même. Si j'ai 5 articles sur 10 marqués BMW, encore une fois, ils doivent d'abord apparaître avant les 5 autres articles.

Est-ce possible?

3
PreeT

Voici une combinaison simplifiée de @PieterGoosen et de @ialocin en utilisant le hook loop_start:

add_action( 'loop_start', function( $q ) {
    if( $q->is_main_query() && $q->is_category( 'car' ) )
        usort( $q->posts, function( $a, $b ){
            return -1 * has_tag( 'bmw', $a ) + 1 * has_tag( 'bmw', $b );            });
}, 10, 2 );

Nous pourrions également utiliser la même méthode pour le filtre the_posts.

Mise à jour:

Pour trier les messages sur la page d'accueil, par le nom de la première catégorie, nous pouvons essayer par exemple:

add_action( 'loop_start', function( $q ) {
    if( $q->is_main_query() && $q->is_home() )
        usort( $q->posts, function( $a, $b ){
            return strcasecmp( 
                get_the_category( $a->ID )[0]->name, 
                get_the_category( $b->ID )[0]->name 
            );
        });
}, 10, 2 );

où nous utilisons strcasecmp pour la comparaison de chaînes sans distinction de casse.

5
birgire

Vous ne pouvez pas faire ce type de tri dans la boucle. Vous pouvez cependant le faire en écrivant votre propre fonction

Voici ma solution: PS! Needs PHP 5.4+

ÉTAPE 1

Créez une fonction appelée wpse161553_loop_sort($tag=''). Cela fonctionnera avec une seule balise avec la requête principale.

ÉTAPE 2

Vous devez obtenir les objets de publication à partir de la requête principale. Ils sont déjà disponibles et ne peuvent être consultés que par $wp_query->posts;. (Pour une liste complète des objets disponibles et leur accès, voir WP_Post ).

ÉTAPE 3

Créez et démarrez un nouveau compteur. Ce compteur sera utilisé pour modifier les clés de tableau à partir de $wp_query->posts; ultérieurement.

ÉTAPE 4

Obtenez le posts_per_page défini dans le back-end. Cette valeur sera ajoutée au compteur pour toutes les publications qui ne possèdent pas la balise souhaitée. Cela fera avancer tous ces messages au-delà des messages de balises souhaités

ÉTAPE 5

Dans la boucle, utilisez has_tag() pour vérifier chaque publication par rapport à la balise souhaitée. Si une publication a une étiquette souhaitée, envoyez la valeur actuelle du compteur à un tableau ($c) telle quelle. Si une publication ne possède pas la balise souhaitée, définissez la valeur du compteur actuel et la valeur posts_per_page sur $c

ÉTAPE 6

Utilisez array_combine pour combiner les deux tableaux. Le tableau nouvellement créé $c remplacera les clés de tableau du tableau de messages

ÉTAPE 7

Utilisez ksort pour trier le nouveau tableau créé avec array_combine en fonction des nouvelles clés. Cela va maintenant trier le tableau de sorte que les articles soient triés par date et aussi, les articles de la balise désirée apparaîtront en premier, puis le reste des articles.

Étape 8

Utilisez array-values pour remettre les touches à zéro à 0 et incrémenter numériquement d’une unité.

ÉTAPE 9

Rembobinez la boucle pour pouvoir la réexécuter

ÉTAPE 10

Désactivez le tableau d'origine dans $wp_query->posts et remplacez-le par le nouveau tableau créé. $wp_query->posts va maintenant contenir un tableau avec le nouvel ordre de post commandé

TOUS ENSEMBLE MAINTENANT !!

Le code suivant va dans votre functions.php

function wpse161553_loop_sort($tag='') {
    global $wp_query;
    $posts = $wp_query->posts; // Gets all post data from the main query

    $c = []; // Going to hold an array of new keys for later use
    if ( have_posts() ) {
        $count = 0; //Start the counter
        $ppp = get_option('posts_per_page'); // Gets the backend posts per page option set. Will be used in conjustion with the counter

        while ( have_posts() ) {
            the_post();
                if( '' != $tag && has_tag($tag)) { // This will be the tag to test against, your desired tag
                    $c[] = $count++;
                }else{
                    $c[] = $ppp + $count++; // Adds posts per page value to each count to advance posts without desired tag past desired tag
                }
        }
    } 

    $posts_reordered  = array_combine( $c, $posts ); // Reset each post from main query's key with the new keys created by $c
        $posts_sorted = ksort($posts_reordered); // Sort the new array according to key
    $posts_reordered  = array_values($posts_reordered); // Reset keys to start at zero and increment by one

    rewind_posts(); // Reset the loop so we can run the loop again

    unset($wp_query->posts); //unset the original $wp_query->posts object array
    $wp_query->posts = $posts_reordered; // Set $wp_query->posts to the new reordered array

}

COMMENT UTILISER CETTE UTILISATION

Dans votre fichier category.php, ou même n'importe quel modèle, collez le texte suivant juste au-dessus de la boucle. Vous n'avez pas besoin de changer autre chose

wpse161553_loop_sort( 'NAME OF THE TAG TO APPEAR FIRST' );

NAME OF THE TAG TO APPEAR FIRST est le nom de la balise souhaitée pour laquelle les messages apparaîtront en premier

3
Pieter Goosen

Juste une brève ébauche d'une idée, alors méfiez-vous, je n'ai pas pensé et testé cela à fond. Je suis cependant certain que vous pouvez effectuer les opérations de tri de cette façon. Ok, ce que je pensais, c’est pourquoi ne pas brancher the_posts et utiliser usort pour faire le tri. Tout le reste, en particulier les conditions conditionnelles, vise simplement à s'assurer que cela n'est pas fait à chaque requête et dépend du cas d'utilisation réel, de sorte que cela doit être ajusté en conséquence.

add_action(
    'the_posts',
    'wpse161553_posts_with_tags_on_top_of_category',
    10,
    2
);
function wpse161553_posts_with_tags_on_top_of_category(
    $posts,
    $wp_query
) {
    // we want this for one specific category
    $the_category = 'abc';
    // we want the post with this tag on top 
    $the_tag      = 'xyz';

    if (
        $wp_query->is_main_query()
        && is_category( $the_category )
    ) {
        // getting an array of post ids from category with tag
        $posts_with_tag = new WP_Query(
            array(
                'category_name' => $the_category,
                'tag'           => $the_tag,
                'fields'        => 'ids'
            )
        );  
        // performing usort on referenced posts object
        usort(
            $posts,
            function (
                $post
            ) use (
                $posts_with_tag
            ) {
                // puts posts from the $posts_with_tag->posts array to the top
                if(
                    in_array (
                        $post->ID,
                        (array) $posts_with_tag->posts 
                     )
                ) {
                    return -1;
                } else {
                    return 1;
                }
            }
        );
    }

    return $posts;
} 
2
Nicolai