Este posibil să sortezi după taxonomie folosind wp_query?

8 apr. 2011, 18:44:50
Vizualizări: 91.6K
Voturi: 62

Întrebarea mea este simplă, folosesc WP_Query pentru a prelua niște postări de tip personalizat filtrând după o taxonomie folosind tax_query.

Problema mea acum este că aș dori să sortez după taxonomie, dar din documentație și căutări pe internet nu găsesc o soluție.

Parametrul orderby din WP_Query îți permite să sortezi după o mulțime de câmpuri, chiar și după câmpuri meta personalizate, dar nu pare să suporte taxonomiile.

Aveți vreo sugestie în direcția corectă?

Vă mulțumesc tuturor.

0
Toate răspunsurile la întrebare 13
7
72

Răspunsul acceptat pentru această întrebare este inacceptabil. Este ilogic să presupui că ordonarea după taxonomie „nu are sens”. Răspunsul pe care l-a dat nu are sens.

Luați în considerare un tip de postare de meniu. Apoi aveți o taxonomie personalizată „CategoriiAlimentare”. Taxonomia CategoriiAlimentare are termenii „MicDejun”, „Pranz” și „Cină”. Dacă trimiteți o interogare care utilizează parametrul tax_query, acum aveți un set de rezultate cu toți termenii, însă aceștia sunt ordonați după data postării.

Pentru a obține ordinea corectă a acestora, relativ la termenii lor, și apoi pentru a le afișa corespunzător în front-end separând postările în categoriile lor respective, trebuie să parcurgeți setul de rezultate, apoi să interogați fiecare postare individuală din setul de rezultate pentru a-i găsi termenii și a-i compara cu termenul curent, să filtrați într-un array și să continuați. Apoi trebuie din nou să parcurgeți noul array pentru afișare. Acest lucru nu este productiv.

Ar fi frumos dacă WP ar avea o opțiune „tax__in” pentru orderby așa cum are una „post__in”, dar din moment ce nu are, fie trebuie să faceți procesul ridicol menționat mai sus, fie să personalizați interogarea prin filtrele 'posts_orderby' și 'posts_join' pentru a ajusta metoda de ordonare și a adăuga termenul în setul de rezultate, respectiv, sau trebuie să faceți o nouă interogare pentru fiecare termen pe care îl filtrați în cadrul secțiunilor html relative la acei termeni.

Cea mai eficientă metodă ar fi modificarea șirului de interogare prin filtre. Cea mai ușoară ar fi să faceți trei interogări separate. API-ul WP ar trebui să se ocupe de ordonarea după taxonomie sau orice parametri de interogare restrictivi. Dacă restricționați o interogare pe baza anumitor condiții, există o probabilitate mare ca mulți să aibă nevoie să ordoneze după aceleași condiții.

28 iul. 2014 14:36:51
Comentarii

Îmi pare rău, dar greșești. Ordonarea după taxonomie nu are sens nici în cazul tău. Ce vrei să afișezi? Toate micile dejunuri primele, urmate de toate cinele, apoi toate prânzurile? Ar trebui să selectezi ce dorești și ordinea în care vrei să apară, dar taxonomia este doar o etichetă de grupare. Nu este o "informație" semnificativă după care ar trebui să ordonezi. Dacă este, atunci nu ar trebui să fie un termen într-o taxonomie, ci ar trebui să-l faci un post-meta în schimb.

Otto Otto
20 oct. 2014 14:57:21

Hai să fim serioși, desigur că vor exista cazuri în care vei dori să ordonezi postările după termenii taxonomiei. Un alt exemplu este un tip de postare Film cu o taxonomie de Evaluare. Într-o listă de filme, este foarte ușor să-ți imaginezi oamenii care doresc să ordoneze lista de filme după evaluare, astfel încât toate filmele cu evaluarea G, apoi PG etc. să apară primele. (În acest caz și în exemplul cu mesele, acestea ar putea fi ordonate după term_id în loc de nume.) Există o zonă mare de cazuri în care probabil că e mai bine să folosești o taxonomie și nu meta, dar este probabil util și ca acea taxonomie să poată fi ordonată.

SeventhSteel SeventhSteel
10 mar. 2015 22:51:49

Evaluările PG și G și altele asemenea sunt o alegere bună de taxonomie, cu excepția faptului că sunt date despre filme specifice. Prin urmare, sunt meta. Sunt date, nu categorii. Doar pentru că ai un număr limitat de opțiuni nu înseamnă că ai o taxonomie. Dacă trebuie să poți ordona, atunci fie o faci meta, fie forțezi ordonarea prin taxonomie folosind cod specific taxonomiei. Apropo, NC17 vine după PG. Deci, oricum ai nevoie de cod pentru a face acea ordonare.

Otto Otto
10 nov. 2015 03:05:34

Știu că am întârziat cu acest comentariu, dar tocmai am dat peste el. Ordonarea după taxonomie poate avea sens în anumite situații. Într-un proiect avem anunțuri de joburi ca tip de postare, iar statul și orașul în care se află jobul sunt taxonomii. Dorim să le putem grupa ușor (afișează toate joburile dintr-un stat sau toate joburile dintr-un oraș), așa că taxonomia a fost cea mai bună soluție. În același timp, există o căutare generală de joburi unde dorim să le sortăm mai întâi după titlu, apoi după stat și apoi după oraș.

Dennis Puzak Dennis Puzak
23 oct. 2018 13:39:32

Un alt caz de utilizare: Un client are o mulțime de articole, fiecare având o categorie. Clientul dorește să existe o pagină care listează toate articolele, care pot fi sortate alfabetic, după dată sau după categorie. Categoriile pot fi și filtrate, dar listarea tuturor articolelor pe categorii în ordine alfabetică nu este un caz de utilizare atât de ciudat și apare destul de des.

W Biggs W Biggs
6 iun. 2019 19:06:27

Încă un caz de utilizare aici: avem o mulțime de 'clienți' într-un tip de postare personalizat și există o taxonomie de regiune care ne permite să indicăm unde își desfășoară afacerile fiecare client. Ni s-a cerut să adăugăm funcționalitatea astfel încât, atunci când un vizitator vede lista de clienți, aceștia să fie ordonați după regiune, cu clienții din apropierea lor primi.

Matt Keys Matt Keys
2 oct. 2020 22:21:23

Otto are dreptate că dacă încerci să faci asta, trebuie să te uiți la structura ta de date; de nouă ori din zece este greșită. ÎNSĂ a insista dogmatic că "toți ceilalți greșesc" nu este inteligent. Iată cazul meu de utilizare: Numele de familie trebuie sortate după prima literă scrisă cu majusculă; de Courcy se plasează sub C și De Haan sub D. Este ușor să folosești o expresie regulată pentru o taxonomie personalizată 'alfabet' care sortează acestea corect; însă acum, pentru a afișa toți oamenii mei cu o simplă interogare (prin 'meta_key' => 'alfabet') nu este posibil. Trebuie să duplic codul meu și să definesc propriul meu filtru 'orderby' => 'quasi_alphabetic_by_title'.

user3445853 user3445853
20 ian. 2023 14:24:43
Arată celelalte 2 comentarii
6
19

Da, dar este destul de complex...

Adaugă în functions.php din tema ta:

function orderby_tax_clauses( $clauses, $wp_query ) {
    global $wpdb;
    $taxonomies = get_taxonomies();
    foreach ($taxonomies as $taxonomy) {
        if ( isset( $wp_query->query['orderby'] ) && $taxonomy == $wp_query->query['orderby'] ) {
            $clauses['join'] .=<<<SQL
LEFT OUTER JOIN {$wpdb->term_relationships} ON {$wpdb->posts}.ID={$wpdb->term_relationships}.object_id
LEFT OUTER JOIN {$wpdb->term_taxonomy} USING (term_taxonomy_id)
LEFT OUTER JOIN {$wpdb->terms} USING (term_id)
SQL;
            $clauses['where'] .= " AND (taxonomy = '{$taxonomy}' OR taxonomy IS NULL)";
            $clauses['groupby'] = "object_id";
            $clauses['orderby'] = "GROUP_CONCAT({$wpdb->terms}.name ORDER BY name ASC) ";
            $clauses['orderby'] .= ( 'ASC' == strtoupper( $wp_query->get('order') ) ) ? 'ASC' : 'DESC';
        }
    }
    return $clauses;
}

    add_filter('posts_clauses', 'orderby_tax_clauses', 10, 2 );

Aceasta este o combinație între cod găsit pe net și modificări personale. Explicarea este destul de dificilă, dar concluzia este că, odată ce rulează acest cod, poți folosi ?orderby=(taxonomy query var)&order=ASC (sau DESC) și va funcționa imediat!

8 apr. 2011 19:36:19
Comentarii

Mulțumesc Drew, voi încerca să rulez acel SQL, trebuie să-l editez puțin, dar ar putea funcționa. Singura mea problemă acum este că s-ar putea să merg în direcția greșită, așa cum a subliniat Otto. Mulțumesc Drew. EDIT - Nu e nevoie să editez, văd unde trebuie făcute ajustările :) Mulțumesc

yeope yeope
8 apr. 2011 19:45:12

Dacă l-ai luat în ultimele două minute, nu va funcționa, ia-l acum, l-am reparat. Era setat pentru două taxonomii specifice, am îmbunătățit codul să funcționeze pentru toate taxonomiile înregistrate.

Drew Gourley Drew Gourley
8 apr. 2011 19:48:14

mulțumesc încă o dată. Doar pentru cazul în care, am încercat soluția ta și funcționează oarecum. De asemenea, dacă altcineva vrea să o folosească, trebuie să schimbi add_filter('posts_clauses', 'orderby_tax_clauses', 10, 2 ); în add_filter('posts_clauses', 'todo_tax_clauses', 10, 2 ); Mulțumesc :)

yeope yeope
9 apr. 2011 01:29:02

Da, acum este rezolvat în blocul de cod, am luat asta dintr-un proiect la care lucrez și am uitat să schimb numele funcției chiar dacă l-am schimbat în hook.

Drew Gourley Drew Gourley
9 apr. 2011 09:39:39

Știi dacă este posibil să ordonezi taxonomiile după ID în loc de nume? Încerc să obțin același rezultat ordonând grupurile de taxonomii după ID

Javier Villanueva Javier Villanueva
17 iul. 2013 01:43:36

am încapsulat asta într-un if (is_admin) {} pentru a evita să fie disponibil în altă parte...

stephendwolff stephendwolff
25 mar. 2022 17:56:09
Arată celelalte 1 comentarii
14
16

Nu, nu este posibil să ordonezi după taxonomie, deoarece, dintr-o anumită perspectivă, acest lucru nu prea are sens.

Taxonomiile sunt modalități de a grupa lucruri împreună. Scopul unei taxonomii pentru articole este să ai termeni în acea taxonomie care sunt partajați între articole. Dacă o taxonomie ar avea termeni folosiți doar pe câte un articol, atunci taxonomia ar fi cam inutilă. Și dacă termenii sunt partajați așa cum ar trebui, atunci ordonarea după ei nu ar produce ceva util.

Ceea ce ar trebui să folosești într-o astfel de situație sunt metadatele articolului (post meta). Poți ordona după metadate, iar acestea sunt unice pentru fiecare articol.

Edit: Cu toate acestea, poți ordona după taxonomie prin crearea unei interogări SQL personalizate folosind un filtru, dar nu poți face acest lucru direct dintr-un WP_Query nemodificat: http://scribu.net/wordpress/sortable-taxonomy-columns.html

Totuși, dacă trebuie să recurgi la astfel de metode, atunci structura datelor tale este greșită din start. "Termenii" din taxonomie nu sunt date reale. Termenii în sine nu au o semnificație intrinsecă, sunt doar etichete pentru gruparea pe care o descriu. Dacă îi tratezi ca date semnificative, atunci ai o problemă la nivel de design.

Taxonomiile grupează lucruri prin atribuirea de termeni. Această grupare este întregul scop al taxonomiilor, termenii sunt doar etichetele acestei grupări. Dacă ai metadate semnificative de atribuit unui articol, atunci ar trebui să folosești metadatele articolului (post meta). Și pe acelea poți să le folosești pentru ordonare, deoarece metadatele articolului folosesc atât chei cât și valori pentru a stoca informații. În cazul unei taxonomii, stochezi doar chei, iar valorile sunt articolele grupate prin acel termen.

Lucrurile sunt mai ușoare pe termen lung dacă folosești abordarea corectă. Nu spun că nu poți face ceva neobișnuit cu taxonomiile, dar îți faci viața mai grea pe termen lung dacă le folosești greșit.

8 apr. 2011 19:20:29
Comentarii

Salut Otto, mulțumesc pentru răspuns. Înțeleg punctul tău de vedere și poate abordez problema greșit. În exemplul meu cu un site de seriale TV, am o taxonomie pentru sezonul 1, sezonul 2, sezonul 3 etc. Așa pot grupa toate serialele TV după numărul sezonului. Apoi am același lucru pentru episoade, Episodul 01, Episodul 02 etc. Ceea ce aș dori este ca atunci când afișez o listă cu toate episoadele, acestea să fie ordonate după episod și sezon. Voi analiza apoi post meta și câmpurile personalizate. Mulțumesc, Otto.

yeope yeope
8 apr. 2011 19:35:58

@yeope taxonomia ta ar trebui să fie "sezoane" și termenii ar trebui să fie sezonul 1, sezonul 2 etc. Presupun că un sezon conține mai multe episoade, așa că poate folosi aceeași taxonomie, "sezoane", iar dacă sunt ierarhice, atunci episodul 1, episodul 2 etc. ar avea termenul părinte "sezonul x". Apoi ai putea interoga un întreg sezon în ordine, cu episoadele așezate corespunzător.

Chris_O Chris_O
8 apr. 2011 22:17:02

@Chris_O Înțeleg, s-ar putea să ai dreptate! Singura problemă pe care o văd este faptul că trebuie să repet termenii "Episodul 1", "Episodul 2" pentru fiecare sezon. De asemenea, să nu pot grupa toate episoadele 1 independent de sezon, dar cred că probabil există o soluție. Mulțumesc, Chris_O.

yeope yeope
9 apr. 2011 01:26:19

Folosirea unei taxonomii pentru episoade nu prea are sens, de fapt, pentru că gruparea este inutilă. Gândiți-vă, dacă aveți "episodul 1" ca termen, atunci grupați episodul 1 cu toate celelalte episoade 1 din toate celelalte seriale TV. Numerele de episod și serie au mai mult sens ca post_meta, pentru că sunt specifice acelui serial anume și nu sunt utile ca grup. Numele serialului TV ar fi util ca termen într-o taxonomie tv-show, pentru că atunci grupați serialul ca întreg.

Otto Otto
15 apr. 2011 22:28:37

Dar o taxonomie pentru serii cam funcționează, dar doar pentru că grupează serialele într-un sezon sau ceva de genul, deși ar trebui să o interogați împreună cu taxonomia tv-show. Într-o astfel de taxonomie de serii, termenii voștri ar fi 1, 2, 3, care reprezintă numărul sezonului în care se afla serialul. Dar tot ați dori mai mult această informație ca postmeta, deoarece doriți să ordonați după ea. Și din moment ce puteți interoga și postmeta, nu prea are sens să o duplicați ca taxonomie.

Otto Otto
15 apr. 2011 22:31:30

@Otto, până la urmă am ales câmpuri personalizate :) Avea mai mult sens.

yeope yeope
4 mai 2011 21:01:59

Otto a urmat acest lucru cu un articol interesant pe blog: Când să (nu) folosești o Taxonomie Personalizată.

Jan Fabry Jan Fabry
5 mai 2011 09:55:59

@otto Mulțumesc pentru share, e foarte util să citesc mai multe detalii despre taxonomii și utilizările lor. În mod special sunt interesat să aflu părerea ta despre o situație precum cea descrisă în postarea Coloane Sortabile de Taxonomii. Care ar fi cea mai bună soluție când vreau să pot interoga toate postările dintr-o gamă de culori, dar și să le pot sorta după culoare? Poate ar fi mai bine să pun o întrebare separată...

Gaffen Gaffen
20 dec. 2013 22:54:54

Dacă vrei să sortezi după acest criteriu, atunci ar trebui să folosești meta date în loc de o taxonomie. Sortarea după taxonomii nu prea are sens, în realitate.

Otto Otto
21 dec. 2013 09:42:43

Mulțumesc @Otto. Deși nu sunt de acord cu afirmația ta: "Cu toate acestea, dacă trebuie să apelezi la astfel de soluții, atunci structura datelor tale este greșită de la început."... Ar putea fi util să poți reordona lista de articole după termenul categoriei în interfața de administrare...

ClemC ClemC
23 mai 2017 16:14:47

@ClemC Nu prea are sens. Articolele pot avea multiple categorii. După ce anume sortezi? Care este criteriul secundar de sortare când două articole au aceeași categorie? Acesta este genul de problemă cu care te confrunți, taxonomiile sunt doar grupări, "termenul" este doar o fațadă frumoasă pentru acea grupare, nu partea importantă. Partea importantă este grupa în sine. Nu ai sorta numele animalelor alfabetic după taxonomia lor linneană. Nu te ajută cu nimic.

Otto Otto
25 mai 2017 00:37:37

Salut @Otto, ai dreptate. Am luat ca referință cazul proiectului meu curent, care este destul de particular... Un CPT (film) care permite doar un singur termen dintr-o taxonomie personalizată (festival) cu butoane radio pentru selecție. Ordinea implicită a listei CPT este după termen (festival), ceea ce în acest caz particular este destul de logic, nu? Nu mă pot gândi la o abordare mai bună privind "designul datelor"... Am implementat "festivaluri" ca o taxonomie pentru că singurele date de care au nevoie sunt descrierea lor și grupează logic "filmele". PS: Îmi cer scuze pentru engleza mea.

ClemC ClemC
25 mai 2017 11:10:46

Da, corect, dar atunci este un grup. Grupezi lucruri împreună. Ce înseamnă "sortează după" în acest context? Dacă ai o serie de lucruri în același grup, atunci poți "selecta după" acel grup, și asta are sens, dar "sortarea" este ceva complet diferit. Sortezi după câmpuri care au valori diferite, nu după câmpuri care au toate aceleași valori.

Otto Otto
25 mai 2017 11:36:37

Îmi pare rău @Otto, abia acum am observat răspunsul tău... Sunt complet de acord cu punctele tale semantice și logica ta. Dar în contextul meu, "sortarea după" ar fi în principal o problemă ergonomică. Gruparea vizuală a proiecțiilor după "festival" ar putea ajuta în mod semnificativ utilizatorul să obțină o imagine de ansamblu bazată pe cel mai important factor pentru el, și asta dintr-o privire. Prin urmare, nu sunt sigur că pot realiza acest lucru altfel decât prin "sortare", care, sunt de acord, nu este un termen potrivit...

ClemC ClemC
19 aug. 2017 22:26:55
Arată celelalte 9 comentarii
5
13

Am ajuns puțin mai târziu la această discuție, dar există o modalitate mai simplă și mai specifică WordPress de a face acest lucru.

Construiește interogarea de taxonomie în mod normal.

$tax_query = array();
$tax_query['relation']="OR";
$tax_query[] = array(
    'taxonomy' => 'product_cat',
    'field'    => 'slug',
    'terms'    => $cat_terms,
);
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;

Configurează argumentele pentru query_posts sau WP_Query

$args = array(
    'post_type'=>'post',
    'posts_per_page'=>12,
    'paged'=>$paged,
    'tax_query' => $tax_query,
);

Înainte de a face apelul query_posts / WP_Query, conectează-te la filtrul orderby și suprascrie-l

add_filter('posts_orderby', 'edit_posts_orderby');
function edit_posts_orderby($orderby_statement) {
    $orderby_statement = " term_taxonomy_id ASC ";
    return $orderby_statement;
}
query_posts($args);
remove_filter('posts_orderby', 'edit_posts_orderby');

Nu uita să elimini filtrul după utilizare...

Această metodă funcționează deoarece tax_query creează automat join-urile necesare, tu trebuie doar să sortezi după unul dintre câmpurile din join.

31 oct. 2014 15:48:14
Comentarii

Ai vreo idee despre cum să sortezi după nume în loc de term_taxonomy_id? Schimbarea term_taxonomy_id în orderby_statement aruncă erori

tehlivi tehlivi
5 oct. 2016 00:52:51

Acesta este răspunsul corect pentru cei interesați!

Mayra M Mayra M
21 iun. 2018 13:43:17

@tehlivi această metodă nu funcționează pentru sortarea după nume deoarece numele se află în tabelul wp_terms. WordPress pare să cache-ze termenii de taxonomie, astfel încât chiar dacă interogarea ta de taxonomie caută după slug sau nume, care sunt de asemenea în tabelul wp_terms, WordPress le procesează prin lista sa cache și le înlocuiește cu ID-uri stocate în term_relationships.term_taxonomy_id, astfel încât nu trebuie să interogheze tabelul wp_terms ca parte a interogării principale. Ceea ce înseamnă că nici numele, nici slug-ul nu sunt incluse în interogarea SQL rezultată. Trebuie să adaugi join-uri.

Ethan C Ethan C
25 oct. 2021 23:34:35

@EthanC salut omule, mulțumesc pentru răspunsul detaliat și sper că dacă cineva va găsi asta în viitor, le va fi util răspunsul tău. Dar pentru mine, este cu siguranță greu să-mi amintesc ceva din 2016. Cred că am ajuns să rulez array-ul printr-o funcție de sortare după ce interogarea s-a finalizat. Sunt sigur că orice dezvoltator care a preluat acel proiect după ce am părăsit compania mă urăște. Haha.

tehlivi tehlivi
27 oct. 2021 00:17:06

@tehlivi Da, am ajuns să ignor interogarea principală în cazul în care unele articole aveau atribuit mai mult de un termen. Am ales în schimb să rulez get_terms() și apoi get_posts pentru fiecare termen. Am adăugat ~15 interogări suplimentare la încărcarea paginii, dar designerul a obținut rezultatul dorit.

Ethan C Ethan C
28 oct. 2021 02:03:53
4

Nu sunt sigur de ce toate soluțiile de aici sunt cam exagerate. OK, a trecut jumătate de decadă, dar acum rulez următorul cod și funcționează:

   <?php // Implicit
    $wheels_args = array(
        'post_type' => 'wheels',
        'posts_per_page' => '96',
        'orderby' => 'taxonomy, name', // Introduceți doar 2 parametri aici, separați prin virgulă
        'order'=>'ASC'
    );
    $loop = new WP_Query($wheels_args);
    ?>

Aceasta va sorta taxonomiile CPT-ului mai întâi după taxonomie în ordine alfabetică și în cadrul acestor grupuri de taxonomii, tot în ordine alfabetică.

6 iul. 2017 15:26:34
Comentarii

@yeope De ce este acesta răspunsul acceptat!? slavă Domnului că am derulat

Juan Solano Juan Solano
22 oct. 2019 02:17:52

nu am reușit să fac asta să funcționeze. poți indica un site cu o explicație pentru asta? nimic aici, care să susțină codul tău

honk31 honk31
9 apr. 2020 20:15:41

Nu se parsează, mai ales cu această virgulă, și este ignorat de WP (6.x).

Picard Picard
2 sept. 2022 17:05:44

Aceasta a funcționat pentru mine, wp 6.5.4. Trebuie să ajustați valoarea după virgulă, de exemplu, dacă taxonomia dvs. ar fi post_tag, ați scrie literal 'orderby' => 'taxonomy, post_tag',.

Tomas Mulder Tomas Mulder
24 iun. 2024 19:21:12
1

Ei bine, aș dori să împărtășesc experiența mea în sortarea postărilor personalizate după categorie/taxonomie.

SITUAȚIA PE WEB

  1. Un site web al unei agenții de turism care rulează pe WordPress
  2. Conținutul principal pe un tip de postare personalizat numit 'ruta'
  3. Taxonomie cu următoarea structură Tip-de-călătorie > continent > țară

PROBLEMA

În paginile de arhivă ale listei de categorii, clientul dorea ca postările să fie sortate după:

  1. Continent, ordonate după numărul de rute din fiecare.
  2. Țară, ordonate alfabetic.

PAȘII URMAȚI

În primul rând, am interceptat cererea din interogarea originală a paginii de arhivă, care arăta astfel:

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID 
FROM wp_posts 
INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) 
WHERE 1=1 
AND ( wp_term_relationships.term_taxonomy_id IN (5,6,7,8,9,10,11,12,13,15,16,17,18,19,20,21,22,23,25,26,28,29,31,32,33,35,38,95,101,102,193) )
AND wp_posts.post_type IN ('ruta', 'nav_menu_item') 
AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 45 
AND wp_posts.post_status = 'private') 
GROUP BY wp_posts.ID 
ORDER BY wp_posts.post_date DESC LIMIT 0, 20

În al doilea rând, am modificat codul SQL în Sequel Pro pentru a se potrivi nevoilor mele. Am ajuns la această variantă (da, probabil poate fi îmbunătățită: cunoștințele mele despre MySQL nu sunt excepționale):

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID, tt1.parent AS pare,
    (
    SELECT COUNT(*) 
    FROM  wp_posts
    INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
    INNER JOIN wp_term_taxonomy AS tt1 ON ( tt1.term_taxonomy_id =      wp_term_relationships.term_taxonomy_id )
    INNER JOIN wp_term_taxonomy AS tt2 ON ( tt2.term_taxonomy_id =  tt1.term_taxonomy_id )
    WHERE 1=1  
    AND tt1.parent = pare
    ) AS Total
FROM  wp_posts
INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
INNER JOIN wp_term_taxonomy AS tt1 ON ( tt1.term_taxonomy_id =      wp_term_relationships.term_taxonomy_id )
INNER JOIN wp_terms ON ( tt1.term_id = wp_terms.term_id )
WHERE 1=1  
AND ( wp_term_relationships.term_taxonomy_id IN (5,6,7,8,9,10,11,12,13,15,16,17,18,19,20,21,22,23,25,26,28,29,31,32,33,35,38,95,101,102,193) ) 
AND wp_posts.post_type IN ('ruta', 'nav_menu_item') 
AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 45 
AND wp_posts.post_status = 'private') 
GROUP BY wp_posts.ID 
ORDER BY
total DESC,
wp_terms.name  

În al treilea rând, am conectat interogarea în fișierul functions.php folosind trei filtre: posts_fields, posts_join și posts_orderby

Codul din functions.php:

function xc_query_fields( $fields ) {

   $fields = "wp_posts.ID, wp_posts.post_title, wp_terms.name, tt1.parent AS pare,
    (
    SELECT COUNT(*) 
    FROM  wp_posts
    INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
    INNER JOIN wp_term_taxonomy AS tt1 ON ( tt1.term_taxonomy_id = wp_term_relationships.term_taxonomy_id )
    INNER JOIN wp_term_taxonomy AS tt2 ON ( tt2.term_taxonomy_id = tt1.term_taxonomy_id )
    WHERE 1=1  
    AND tt1.parent = pare
    )
    AS Total";
     return $fields;
}


function xc_query_joins( $join ) {
$join .= "INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
   INNER JOIN wp_term_taxonomy AS tt1 ON ( tt1.term_taxonomy_id = wp_term_relationships.term_taxonomy_id )
   INNER JOIN wp_terms ON ( tt1.term_id = wp_terms.term_id )";
 return $join;
}


function xc_query_orderby( $join ) {
    $join = "total DESC, wp_terms.name ";
    return $join;
 }

În final, am declanșat filtrele din hook-ul pre_get_post în funcție de anumite condiții

function filtra_queries( $query )
{

  if (  is_archive()  && $query->is_main_query() && !is_admin()  ) {

$rutes = array('viajes-privados', 'asia', 'africa', 'oceania', 'america', 'oriente-proximo');

if  ( in_array( $query->get('category_name'), $rutes ) ) 
  {
  add_filter( 'posts_fields', 'xc_query_fields' );
  add_filter( 'posts_join', 'xc_query_joins' );
  add_filter( 'posts_orderby', 'xc_query_orderby' );
}// end if in_array

  }// end if is_archive

}
 add_filter('pre_get_posts', 'filtra_queries');

Sper că acest lucru poate ajuta pe cineva

4 ian. 2015 17:09:00
Comentarii

Bună treabă, ridicol că a fost nevoie de această cantitate de cod pentru a sorta ceva după o taxonomie. O problemă uriașă în WP.

serraosays serraosays
21 iul. 2017 02:27:03
0

Am avut o problemă foarte asemănătoare cu care m-am confruntat: vreau să ordonez un arhiv de postări personalizate (articole din revistă) după o taxonomie personalizată (numere). Nu folosesc niciodată interogări SQL directe pe site-ul meu - și de obicei dacă sunteți ca celelalte răspunsuri de aici - trebuie să vă reconsiderați abordarea.

PROBLEME:

1) WordPress nu vă permite să ordonați taxonomiile într-un mod inteligent.

2) WordPress pur și simplu nu permite folosirea taxonomiilor în parametrul orderby pentru WP_Query pe tipuri de postări (așa cum a explicat Otto).

SOLUȚII:

1) Sortarea taxonomiilor se realizează cel mai bine în acest moment cu plugin-ul Custom Taxonomy Order NE. Acesta vă permite să ordonați taxonomia printr-un editor WYSIWYG în wp-admin, ceea ce nu este modul meu preferat, dar nu am găsit ceva mai bun.

Când configurați plugin-ul, veți obține ceva similar cu ceea ce am făcut eu aici. Luați notă de opțiunea Auto-sort Queries of this Taxonomy - setați-o la Custom Order as Defined Above; astfel obțineți ordonarea necesară. Captură de ecran:

Afișaj Custom Taxonomy Order NE

2) Cu o taxonomie sortată în loc, puteți acum crea o serie de interogări WP_Query care parcurg fiecare termen, creând efectiv un arhiv ordonat după taxonomie. Folosiți get_terms() pentru a crea un array cu toți termenii taxonomiei, apoi rulați un foreach pentru fiecare termen. Acest lucru creează o interogare WP_Query pentru fiecare termen care va returna toate postările pentru acel termen, creând efectiv un arhiv ordonat după termenii taxonomiei. Codul pentru implementare:

  // Obțineți termenii și puneți-i într-un array
  $issue_terms = get_terms([
    'taxonomy' => 'issues',
    'hide_empty' => false,
  ]);

  // Rulați foreach pentru fiecare termen pentru a configura interogarea și afișarea postărilor
  foreach ($issue_terms as $issue_term) {
    $the_query = new WP_Query( array(
      'post_type' => 'post',
      'tax_query' => array(
        array(
          'taxonomy' => 'issues',
          'field' => 'slug',
          'terms' => array( $issue_term->slug ),
          'operator' => 'IN'
        )
      )
    ) );

    // Rulați bucla pentru fiecare interogare
    while($the_query->have_posts()) :
      $the_query->the_post();

      // AFIȘAREA ȘABLONULUI PENTRU FIECARE POSTARE

    endwhile;
  }

Lectură recomandată pe acest site: Afișați toate postările dintr-un tip personalizat, grupate după o taxonomie personalizată

10 apr. 2017 17:45:43
0

Iată soluția pe care am folosit-o pentru această problemă specifică. Această soluție este pentru cazurile extreme în care nu este posibil să folosești un filtru pre_get_posts și există deja paginare pe interogare (de exemplu: WooCommerce):

global $wpdb;

$taxonomies = array('my-tax-1', 'my-tax-2', 'my-tax-3');

$orderby = "'".implode("', '", array_keys($taxonomies))."'";
$id_sql = $GLOBALS['wp_query']->request;

$id_sql = preg_replace('/LIMIT\s+\d+\s?,?\s\d*/', '', $id_sql);
$id_sql = str_replace('SQL_CALC_FOUND_ROWS', '', $id_sql);

$term_sql = "SELECT
  tt.taxonomy AS `taxonomy`,
  t.name AS `term_name`,
  t.slug AS `term_slug`,
  count(*) AS `term_count`
FROM ({$id_sql}) p 
JOIN wp_term_relationships tr
  ON p.ID = tr.object_id
JOIN wp_term_taxonomy tt
  ON tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms t
  ON tt.term_id = t.term_id
WHERE tt.taxonomy IN ({$orderby})
GROUP BY t.slug
ORDER BY
  FIELD(tt.taxonomy, {$orderby})"; // Adaugă aici ordonarea suplimentară specifică

$results = $wpdb->get_results($term_sql, ARRAY_A);

Am folosit acest cod pentru a crea un meniu de navigare ordonat după taxonomie, termen și număr de postări pe termen.

Dacă dorești doar postările, modifică interogarea în SELECT p.* și GROUP BY p.ID

24 mar. 2017 18:48:47
3

Îmi place să sortez termenii manual, așa că folosesc un plugin pentru asta. Și sunt un fan al filtrului pre_get_posts, așa că am luat exemplul funcțional corect al lui Drew Gourley și l-am adaptat să funcționeze cu acesta. Deci, acesta este un caz oarecum special, dar postez oricum, în caz că ajută pe cineva. Următorul cod se adaugă în functions.php sau într-un plugin personalizat.

Mai întâi, să începem cu filtrul. Sortăm tipul de postare personalizat music după taxonomia personalizată style:

function so14306_pre_get_posts($query)
{
    if (is_admin()) :
        return;
    endif;

    if ($query->is_main_query()) :
        if (is_post_type_archive('music')) :
            $query->set('orderby', 'style');

        endif;
    endif;
}

add_action('pre_get_posts', 'so14306_pre_get_posts');

Apoi apelăm filtrul post_clauses:

function so14306_posts_clauses($clauses, $wp_query)
{
    global $wpdb;

    if (isset($wp_query->query_vars['orderby']) && $wp_query->query_vars['orderby'] === 'style') {
        $orderby = $wp_query->query_vars['orderby'];
        $clauses['join'] .= <<<SQL
LEFT OUTER JOIN {$wpdb->term_relationships} ON {$wpdb->posts}.ID={$wpdb->term_relationships}.object_id
LEFT OUTER JOIN {$wpdb->term_taxonomy} USING (term_taxonomy_id)
LEFT OUTER JOIN {$wpdb->terms} USING (term_id)
SQL;
        $clauses['where'] .= " AND (taxonomy = '{$orderby}' OR taxonomy IS NULL)";
        $clauses['groupby'] = "object_id";
        $clauses['orderby'] = "GROUP_CONCAT({$wpdb->terms}.term_order ORDER BY {$wpdb->terms}.term_order ASC) ASC";
        $clauses['orderby'] .= ", {$wpdb->posts}.post_name ASC";
    }

    return $clauses;
}

add_filter('posts_clauses', 'so14306_posts_clauses', 10, 2);

Acum tot ce trebuie să faci este să sortezi taxonomiile cu următorul plugin: Simple Custom Post Order. Acest plugin este obligatoriu pentru această soluție, deoarece adaugă coloana term_order în baza de date!

Iar această linie: $clauses['orderby'] .= ", {$wpdb->posts}.post_name ASC" sortează postările după titlu, astfel încât sortarea completă a soluției de mai sus este: termen de taxonomie => titlul postării.

9 apr. 2020 19:33:04
Comentarii

Mulțumesc mult, acest lucru este foarte util. Este minunat să ai o modalitate de a ordona vizual. Știi de ce partea "OR taxonomy IS NULL" este acolo? Pare a fi ceva care nu este necesar.

Jordan Carter Jordan Carter
6 oct. 2021 22:14:27

Afișează primul termen corect, dar după acele postări următorul termen nu urmează logic ordinea din meniu stabilită cu SCP Order. Mă întreb dacă este pentru că încerc să fac asta cu produse, iar WooCommerce are deja o ordine pentru atribute... poate cele două intră în conflict. În baza de date însă ID-urile din coloana term_order sunt corecte...

Jordan Carter Jordan Carter
6 oct. 2021 22:32:44

Schimbarea liniei GROUP_CONCAT orderby în următoarea variantă pare să ajute: $clauses['orderby'] = "{$wpdb->terms}.term_order ASC";

Jordan Carter Jordan Carter
6 oct. 2021 22:44:09
1

O metodă destul de simplă de a face acest lucru este să adăugați o funcție care să facă următoarele:

  1. Când articolul este publicat...
  2. Obțineți ID-ul/slug-ul/etc. al categoriei...
  3. Salvați-l ca o valoare meta personalizată pentru articol

Apoi, în bucla (loop) WordPress, ordonați articolele după acea valoare meta.

De exemplu:

// 1
add_action( 'publish_post', 'save_and_add_meta' );

function save_and_add_meta($post_id){

        //Elimină temporar acțiunea pentru a evita o buclă infinită
        remove_action( 'publish_post', 'save_and_add_meta' );

        // 2            
        $category_slug = get_the_terms($post_id, 'your_taxonomys_name')[0]->slug;

        //3
        add_post_meta($post_id, 'cat_slug', $category_slug);

        //Adaugă acțiunea înapoi
        add_action( 'publish_post', 'save_and_add_meta' );
}

Apoi, în interogarea WordPress (WP_Query), adăugați în argumentele $args:

'meta_key' => 'cat_slug',
'orderby' => 'meta_value',
'order' => 'DESC',

Această metodă funcționează dacă puteți restricționa utilizatorii să atribuie doar o singură categorie per articol sau dacă categoriile sunt mutual exclusive. Dacă atribuie mai multe categorii, articolul ar fi exclus din una dintre ele.

11 sept. 2020 18:56:41
Comentarii

Mă gândesc la același lucru, deși duplică datele.

Sisir Sisir
22 sept. 2021 23:18:54
1

Este ca o interogare înaintea interogării, dar nu va deranja dacă nu interogăm prea multe articole... Ideea este de a modifica interogarea principală, astfel încât să nu fie nevoie să mergem la șabloane și să generăm noi interogări și bucle...

function grouped_by_taxonomy_main_query( $query ) {

    if ( $query->is_home() && $query->is_main_query() ) { // Rulează doar pe pagina principală

        $post_ids = array();

        $terms = get_terms('my_custom_taxonomy');

        foreach ( $terms as $term ) {
            $post_ids = array_merge( $post_ids, get_posts( array( 
                'posts_per_page' => 4, // după cum dorești...
                'post_type' => 'my_custom_post_type', // Dacă este necesar... Implicit sunt articolele
                'fields' => 'ids', // vrem doar ID-urile pentru a le folosi mai târziu în 'post__in'
                'tax_query' => array( array( 'taxonomy' => $term->taxonomy, 'field' => 'term_id', 'terms' => $term->term_id, )))) // obținerea articolelor din termenul curent
            );
        }

        $query->query_vars['post_type'] = 'my_custom_post_type'; // Din nou, dacă este necesar... Implicit sunt articolele
        $query->query_vars['posts_per_page'] = 16; // Dacă este necesar...
        $query->query_vars['post__in'] = $post_ids; // Filtrăm cu ID-urile articolelor obținute mai sus
        $query->query_vars['orderby'] = 'post__in'; // Aici păstrăm ordinea generată în bucla termenilor
        $query->query_vars['ignore_sticky_posts'] = 1; // Dacă nu dorești ca articolele lipicioase să schimbe ordinea

    }
}

// Conectează funcția de mai sus la acțiunea pre_get_posts
add_action( 'pre_get_posts', 'grouped_by_taxonomy_main_query' );
22 apr. 2017 09:38:39
Comentarii

Acesta va eșua, nu poți folosi get_posts sau WP_Query în interiorul pre_get_posts, va crea o buclă infinită. Deoarece atunci când folosești get_posts sau WP_Query, acesta va declanșa hook-ul pre_get_posts și va cauza o buclă infinită, chiar dacă verifici is_main_query, nu se va opri și va rula continuu.

Den Pat Den Pat
23 mar. 2022 12:31:21
0

Câteva răspunsuri sunt destul de complexe, am scris această soluție care este destul de simplă de înțeles (cred/sper):

$args = array( 'post_type' => 'Teammember','posts_per_page' =>  -1);
$loop = new WP_Query($args);
if ( $loop->have_posts() ) {
     while ( $loop->have_posts() ) {
         $loop->the_post();
         $id = get_the_id();
         $name = get_the_terms( get_the_ID(), 'teammember-category' );
         $sort[$id] = $name[0]->name;
    }
}
wp_reset_postdata();
asort($sort);
$result = array_keys($sort);

Acum variabila $result conține toate ID-urile postărilor, ordonate ascendent după numele taxonomiei personalizate. Atenție: dacă o postare conține mai multe categorii, este necesară o soluție diferită.

Puteți folosi ID-urile într-o funcție foreach, cam așa:

foreach($result as $id){
$image = get_the_post_thumbnail($id);
...etc.
} 

Sau puteți face o a doua interogare astfel:

$loopnew = new WP_Query(array('post_type' => 'Teammember','post__in'=> $result));
if ( $loopnew->have_posts() ) {
     while ( $loopnew->have_posts() ) {
         $loopnew->the_post();
         ...etc.
     }
 }
15 feb. 2023 19:45:56
0
-1

Este cam enervant că WordPress nu te lasă să faci asta și te forțează să ai practic două câmpuri cu aceeași informație...

DAR voi posta aici soluția mea. Ideea este să trecem toți termenii de taxonomie selectați în metadatele postului.

(Atenție, va trebui să ajustați dacă taxonomia dvs. permite valori multiple)

//adaugă acest hook pentru a salva automat termenii ca metadate la salvarea unui post
add_action('save_post', 'add_custom_taxonomies_as_post_meta', 10, 1);
function add_custom_taxonomies_as_post_meta($id)
{
  $current_post = get_post($id);
  $taxonomies  = get_object_taxonomies($current_post);
  foreach ($taxonomies as $tax) {
    $post_terms = get_the_terms($id, $tax);
    $term = $post_terms[0];
    add_post_meta($id, $tax,  $term->name, true);
  }
}

După ce adăugați acest cod în functions.php, puteți folosi meta_key și orderby ca de obicei pentru a ordona postările astfel:

   'meta_key' => TAXONOMIA-DVS,
    'orderby'    => array(
      'meta_value' => 'ASC'
    )

Sper că acest lucru este util pentru cineva.

14 iul. 2022 15:43:13