it-swarm-eu.dev

Použití wp_query je možné objednat podle taxonomie?

Moje otázka je jednoduchá, používám službu WP_Query k načtení některých vlastních příspěvků typu filtrování pomocí taxonomie pomocí tax_query.

Můj problém je, že bych rád objednal taxonomii, ale z dokumentace a vyhledávání na webu nemohu najít řešení.

Uspořádání ve WP_Query vám umožní objednat partu polí dokonce i vlastní meta pole, ale nezdá se, že by podporoval taxonomii.

Nějaké ukazatele správným směrem?

Děkuji vám všem.

48
yeope

Ne, to není možné objednat podle taxonomie, protože z určitého typu stanoviska to ve skutečnosti nedává smysl.

Taxonomie jsou způsoby, jak seskupovat věci dohromady. Takže smysl mít taxonomii na příspěvcích by skutečně měl mít termíny v této taxonomii, které jsou sdíleny mezi příspěvky. Pokud by taxonomie měla termíny, které byly použity pouze na jednom příspěvku, pak by to způsobilo, že taxonomie bude zbytečná. A kdyby tyto podmínky byly sdíleny tak, jak by měly být, pak by jejich objednání nevedlo k ničemu zvlášť užitečnému.

V takové situaci byste měli používat meta post. Můžete si objednat poštou a je jedinečný pro každý příspěvek.

Edit: To znamená, že můžete objednat podle taxonomie pomocí vlastního dotazu SQL pomocí filtru, prostě to nemůžete udělat z nemodifikovaného WP_Query: http://scribu.net/wordpress/sortable-taxonomy-columns. html

Nicméně, pokud jste se uchýlit k tomu, že něco takového, pak vaše data design struktury je špatné na prvním místě. "Pojmy" v taxonomii nejsou skutečná "data". Samotné termíny nemají žádný vlastní význam, jsou to jen popisky pro konkrétní skupinu, kterou popisují. Pokud s nimi zacházíte jako s významnými daty, pak máte základní konstrukční chybu.

Taxonomie seskupí věci přiřazením termínů k nim. Toto seskupení je celým bodem taxonomií, termíny jsou jen pěkné tváře na seskupení. Pokud máte smysluplná metadata pro přiřazení příspěvku, měli byste místo toho použít meta příspěvku. A že můžete objednat podle, protože pošta meta používá k ukládání informací obě klíče a hodnoty. S taxonomií skutečně ukládáte pouze klíče, jejichž hodnoty jsou příspěvky seskupené podle tohoto výrazu.

Věci jsou z dlouhodobého hlediska snazší, pokud k tomu použijete správný přístup. I když neříkám, že s taxonomií nemůžete dělat něco zvláštního, děláte to, co je pro vás v dlouhodobém horizontu obtížnější.

13
Otto

Přijatá odpověď na tuto otázku je nepřijatelná. Je nelogické předpokládat, že objednávka podle daně „nedává smysl“. Odpověď, kterou dal, nemá smysl.

Zvažte, zda máte typ nabídky. Pak máte vlastní daň "FoodCategories". Daň FoodCategories má výrazy „Snídaně“, „Oběd“ a „Večeře“. Pokud odešlete dotaz s použitím parametru tax_query param, máte nyní nastavený výsledek se všemi podmínkami, ale jsou seřazeny podle data po odeslání.

Chcete-li získat správné pořadí z nich, ve vztahu k jejich podmínkám, a pak se správně zobrazovat na předním konci oddělením příspěvků do různých kategorií, musíte se projít přes sadu výsledků a poté zadat dotaz každému jednotlivému příspěvku v rámci kategorie. Výsledek nastaven tak, aby našel termíny a porovnal se s aktuálním termínem, filtroval do pole a pokračoval v celém textu. Pak musíte znovu projít novým polem pro zobrazení. To není produktivní.

Bylo by hezké, kdyby WP měla možnost "tax__in" orderby, jak to dělá "post__in", ale protože to tak není, buď musíte udělat výše uvedený směšný proces; upravte dotaz sami pomocí filtru 'posts_orderby' a filtru 'posts_join', abyste mohli upravit metodu uspořádání a přidejte termín do sady výsledků; nebo musíte vytvořit nový dotaz pro každý výraz, který filtrujete v rámci částí html vzhledem k těmto výrazům.

Nejúčinnější by bylo změnit řetězec dotazu pomocí filtrů. Nejjednodušší by bylo provedení tří samostatných dotazů. Rozhraní WP API by mělo být zpracování objednávek podle daní nebo všech omezujících parametrů dotazu. Pokud omezujete dotaz na základě určitých podmínek, je velká pravděpodobnost, že mnoho z nich bude muset objednávat podle stejných podmínek.

43
Aryan Duntley

Ano, ale je to dost ...

Přidat do function.php ve vašem motivu:

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

Tohle je frankensteined od některých nalezených věcí a některých věcí, které jsem udělal sám. Vysvětlení je dost těžké, ale spodní řádek je s tímto spuštěním, můžete dát? Orderby = (taxonomie dotaz var) & order = ASC (nebo DESC) a ona bude mít hned!

15
Drew Gourley

Přijedu pozdě do hry tady, ale je to jednodušší více WordPressy způsob, jak toho dosáhnout.

Vytvořte si daňový dotaz jako obvykle.

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

Nastavte args pro query_posts nebo WP_Query

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

Než provedete volání query_posts/WP_Query, zavěste do objednávkového filtru a přepíše jej

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

nezapomeňte poté filtr odstranit ...

to funguje b/c tax_query vytvoří spojení atd. pro vás, stačí si objednat podle jednoho z polí ze spojení.

9
Francis Yaconiello

Rád bych vystavil své zkušenosti s tříděním vlastních typů příspěvků podle kategorie/taxonomie.

WEB

  1. Webové stránky cestovní kanceláře běží na WordPress
  2. Hlavní obsah vlastního typu příspěvku nazvaný „ruta“
  3. Taxonomie s touto strukturou Typ cestování> kontinent> země

PŘÍPAD

V archivních stránkách seznamu kategorií klient chtěl, aby byly příspěvky seřazeny podle

  1. Kontinent, seřazený podle počtu tras na každém z nich.
  2. Země, seřazená abecedně.

KROKY

Nejprve , zachytím požadavek z nezměněného dotazu na archivní stránku, který se podobal tomuto:

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

Druhé , upravil jsem kód sql v Sequel Pro proti databázi, aby odpovídal mým potřebám. Vycházím s tím (ano, pravděpodobně to může být vylepšeno: moje znalosti o MySQL nejsou vynikající):

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  

Třetí , připojil jsem dotaz na soubor functions.php se třemi filtry: posts_fields, posts_join a posts_orderby

Kód v function.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;
 }

Nakonec Spustil jsem filtry z háku pre_get_post podle některých podmínek

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

Doufám, že to může někomu pomoci

2
Xavier Caliz

Měl jsem velmi podobný problém, který jsem řešil: Chci si objednat vlastní post-type archiv (články v časopisech) vlastní taxonomií (problémy). Nikdy na svých stránkách neprovádím přímé dotazy SQL - a obvykle, pokud jste jako tyto další odpovědi - musíte přehodnotit svůj přístup.

PROBLÉMY:

1) Wordpress neumožňuje objednávat taxonomie jakýmkoliv inteligentním způsobem.

2) Wordpress prostě neumožňuje použití orderby pro použití taxonomií na post-type WP_Query (jak je uvedeno Otto).

ŘEŠENÍ:

1) Třídění taxonomií je nejlépe dosaženo pomocí Custom Order of the Taxonomy Order NE plugin. To vám umožní objednat taxonomii přes WYSIWYG v wp-admin který není jak já bych dělal to ale já jsem nenašel nic lepšího.

Když nastavíte plugin, dostanete něco podobného tomu, co jsem tady udělal. Poznamenejte si volbu Auto-sort Queries of this Taxonomy - nastavte na Custom Order as Defined Above; to vám zajistí objednání, které potřebujete. Snímek obrazovky:

 Custom Taxonomy Order NE display 

2) Se zavedenou tříděnou taxonomií můžete nyní vytvořit řadu volání WP_Query, která procházejí každým termínem, čímž se efektivně vytvoří archiv seřazený podle taxonomie. Použijte get_terms() k vytvoření pole všech daňových podmínek a poté spusťte foreach v každém termínu. To vytvoří WP_Query pro každou položku termín, který vrátí všechny příspěvky pro daný termín, efektivně vytvářet archiv seřazený podle taxonomie termín. Kód, aby se to stalo:

  // Get your terms and put them into an array
  $issue_terms = get_terms([
    'taxonomy' => 'issues',
    'hide_empty' => false,
  ]);

  // Run foreach over each term to setup query and display for posts
  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'
        )
      )
    ) );

    // Run loop over each query
    while($the_query->have_posts()) :
      $the_query->the_post();

      // YOUR TEMPLATE OUTPUT FOR EACH POST

    endwhile;
  }

Související čtení na těchto stránkách: Zobrazit všechny příspěvky ve vlastním typu příspěvku seskupené podle vlastní taxonomie

2
staypuftman

Nejsem si jistý, proč jsou zde všechna řešení do značné míry přehnaná. OK, je to před půl rokem, ale právě teď spouštím následující kód a funguje to:

   <?php // Default
    $wheels_args = array(
        'post_type' => 'wheels',
        'posts_per_page' => '96',
        'orderby' => 'taxonomy, name', // Just enter 2 parameters here, seprated by comma
        'order'=>'ASC'
    );
    $loop = new WP_Query($wheels_args);
    ?>

Toto bude třídit taxonomie vašeho CPT nejprve jeho taxonomií v abecedním pořadí a uvnitř těchto skupin taxonomie als podle abecedního pořadí.

1
user3135691

Zde je řešení, které jsem použil pro tento konkrétní problém. Toto řešení je pro extrémní případy, kdy není možné použít filtr pre_get_posts a na dotazu existuje existující stránkování (např .: 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})"; // Add further specific ordering here

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

Použil jsem to, abych vytvořil navigační menu seřazené podle taxonomie, termínu a počtu příspěvků za období.

Pokud chcete, aby se příspěvky zobrazovaly, změňte dotaz na SELECT p.* a GROUP BY p.ID

1
CodeShaman

Je to jako dotaz před dotazem, ale nebudete se obtěžovat, pokud nebudeme dotazovat příliš mnoho příspěvků ... Cílem je upravit hlavní dotaz, abychom nemuseli chodit do šablon a generovat nové dotazy a smyčky ...

function grouped_by_taxonomy_main_query( $query ) {

    if ( $query->is_home() && $query->is_main_query() ) { // Run only on the homepage

        $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, // as you wish...
                'post_type' => 'my_custom_post_type', // If needed... Default is posts
                'fields' => 'ids', // we only want the ids to use later in 'post__in'
                'tax_query' => array( array( 'taxonomy' => $term->taxonomy, 'field' => 'term_id', 'terms' => $term->term_id, )))) // getting posts in the current term
            );
        }

        $query->query_vars['post_type'] = 'my_custom_post_type'; // Again, if needed... Default is posts
        $query->query_vars['posts_per_page'] = 16; // If needed...
        $query->query_vars['post__in'] = $post_ids; // Filtering with the post ids we've obtained above
        $query->query_vars['orderby'] = 'post__in'; // Here we keep the order we generated in the terms loop
        $query->query_vars['ignore_sticky_posts'] = 1; // If you dont want your sticky posts to change the order

    }
}

// Hook my above function to the pre_get_posts action
add_action( 'pre_get_posts', 'grouped_by_taxonomy_main_query' );
0
Marcelo Viana