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?
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.
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' );
où NAME OF THE TAG TO APPEAR FIRST
est le nom de la balise souhaitée pour laquelle les messages apparaîtront en premier
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;
}