Filtrare get_categories() pentru termen de taxonomie în WordPress

1 dec. 2010, 09:36:30
Vizualizări: 18.1K
Voturi: 2

Vreau să afișez o categorie doar dacă un post (personalizat) se află în acea categorie ȘI regiunea = $name pentru acel post.

De exemplu, am un post personalizat (tip "business") numit "Mamma Mia" în subcategoria: "pizzerii" (și în categoria părinte "mâncare"), și în regiunea "Rotterdam" (taxonomie personalizată: "region", termen de taxonomie: "rotterdam").

=> afișează categoria "pizzerii" (și categoria părinte "mâncare")

Doar că nu am nicio idee cum să realizez asta. Aș aprecia orice ajutor pentru această problemă.

<?php 

// $filter = array('region'=>$name); 

$categories = get_categories(); 
foreach ($categories as $cat) 
{ 
    if($cat->parent < 1) 
    { 
    $cat_name = $cat->cat_name; 
    $catid = get_cat_ID( $cat_name ); 
    echo $cat_name. '<br/>'; 

    $args=array( 
      'orderby' => 'name', 
      'order' => 'ASC', 
      'child_of' => $catid 
      ); 
    $categories=get_categories($args); 
      foreach($categories as $category) {  
        echo '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "Vezi toate postările din %s" ), $category->name ) . '" ' . '>' . $category->name.'</a><br/>'; 
        }  

    } 
} 

// print_r($categories);  


?>
3
Comentarii

Deci vrei să listezi termenii de categorie care au business-uri asignate și care sunt, de asemenea, asignate unui anumit region?

Rarst Rarst
6 dec. 2010 15:04:01

@Henk, poți explica puțin mai în detaliu unde ai vrea să faci asta? Pe o pagină cu un singur post? Pe o arhivă de taxonomie? Pe o arhivă de categorie?

TheDeadMedic TheDeadMedic
6 dec. 2010 15:30:44

Cred că putem generaliza acest lucru la căutare facetată. Există un plugin cu acest nume, dar se pare că nu poți combina mai multe taxonomii. Pentru că acest subiect este atât de interesant, am adăugat recompensa.

Jan Fabry Jan Fabry
6 dec. 2010 16:47:49
Toate răspunsurile la întrebare 8
1

intenția este de a afișa o listă de categorii, dar doar acele categorii care au articole unde taxonomia personalizată regiune este setată pe Rotterdam

Aceasta se realizează în plugin-ul Query Multiple Taxonomies:

http://plugins.trac.wordpress.org/browser/query-multiple-taxonomies/trunk/core.php?rev=308185#L10

8 dec. 2010 08:20:26
Comentarii

Și mai exact, în widget-ul de navigare în detaliu. Excelent! Acum ar trebui doar extins pentru a afișa și categoriile părinte: dacă un articol este atașat la Pizzerii, îl voi vedea și când navighez în Mâncare, dar Mâncare nu este afișat în widget dacă articolul nu este explicit atașat la el.

Jan Fabry Jan Fabry
8 dec. 2010 09:27:25
3

Ideea generală - interogare pentru un set specific de articole, colectarea tuturor categoriilor lor, filtrare, lăsând funcția să le modeleze.

Cod generic:

$posts = get_posts(array(
    'tag' => 'linux' // Obține articolele cu eticheta 'linux'
));

$categories = array();

foreach( $posts as $post ) {

    $cats = get_the_category($post->ID); // Obține categoriile pentru fiecare articol

    foreach($cats as $c)
        $categories[] = $c->term_id; // Adaugă ID-urile categoriilor în array
}

$categories = array_unique($categories); // Elimină duplicatele
sort($categories); // Sortează categoriile
$categories = implode(',', $categories); // Transformă array-ul în string separat prin virgulă

$result = get_categories(array(
    'include' => $categories // Obține detaliile categoriilor după ID-uri
));

Problemele sunt - după cum îmi amintesc, interogările decente pentru taxonomii multiple vor apărea abia în WP 3.1 și acest lucru ar putea fi foarte intensiv, așa că va necesita caching (probabil pentru fiecare regiune).

6 dec. 2010 15:22:21
Comentarii

Cum afectează parametrul include rezultatele ierarhice? Dacă există câteva postări în Pizzerii, dar niciuna direct atașată părintelui său Mâncare, va fi afișat Mâncare? Sau postările sunt atașate automat și categoriilor părinte?

Jan Fabry Jan Fabry
6 dec. 2010 16:24:36

@Jan Fabry am testat, dacă doar ID-ul categoriei copil este transmis către get_categories(), atunci categoria părinte nu este returnată. :( Deci ar mai fi necesar un pas în care să parcurgem categoriile și să obținem părinții. Un haos și mai mare.

Rarst Rarst
6 dec. 2010 16:34:06

Cred că ar trebui să ne orientăm spre o interogare SQL personalizată, care să alăture mai multe tabele de taxonomie. Și caching, desigur.

Jan Fabry Jan Fabry
6 dec. 2010 16:41:17
0

Pe versiunea de WordPress pe care o folosesc, adică versiunea 3.1.2. Dacă ai adăuga 'taxonomy' => 'taxonomy_term' în array-ul de argumente, ar trebui să funcționeze. Așadar, iată o modificare a codului tău original pentru a include taxonomia în array. Nu știu însă numele taxonomiei pe care încerci să o folosești sau nu:

<?php 

// $filter = array('region'=>$name); 

$categories = get_categories(); 
foreach ($categories as $cat) 
{ 
    if($cat->parent < 1) 
    { 
    $cat_name = $cat->cat_name; 
    $catid = get_cat_ID( $cat_name ); 
    echo $cat_name. '<br/>'; 

    $args=array( 
      'taxonomy' => 'taxonomy_term', 
      'orderby' => 'name', 
      'order' => 'ASC', 
      'child_of' => $catid 
      ); 
    $categories=get_categories($args); 
      foreach($categories as $category) {  
        echo '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "Vezi toate articolele din %s" ), $category->name ) . '" ' . '>' . $category->name.'</a><br/>'; 
        }  

    } 
} 

// print_r($categories);  
?>
31 mai 2011 17:50:16
0

Am adaptat răspunsul lui @rarst de mai sus pentru a utiliza 3 taxonomii personalizate. Vreau să afișez doar termenii care sunt atașați la unul sau mai multe dintre postările din buclă.

Iată funcția pe care am adăugat-o în functions.php:

function dv_setup_sidebar_cats() {
    global $wp_query;

    $designers = array();
    $sizes     = array();
    $colors    = array();

    foreach( $wp_query->posts as $post ) {

        $des   = get_the_terms($post->ID, 'designer');
        $siz   = get_the_terms($post->ID, 'size');
        $col   = get_the_terms($post->ID, 'color');    

        foreach($des as $d) {
            $designers[] = $d->term_id;
        }

        foreach($siz as $s) {
            $sizes[] = $s->term_id;
        }

        foreach($col as $c) {
            $colors[] = $c->term_id;
        }

    }

    if ( !empty($designers) ) {
        $designers = array_unique($designers);
        sort($designers);
        $designers = implode(',', $designers);

        $dresult   = get_categories(array(
            'include'  => $designers,
            'taxonomy' => 'designer'
        ));
    }

    if ( !empty($sizes) ) {
        $sizes = array_unique($sizes);
        sort($sizes);
        $sizes = implode(',', $sizes);

        $sresult   = get_categories(array(
            'include'  => $sizes,
            'taxonomy' => 'size'
        ));
    } 

    if ( !empty($colors) ) {
        $colors = array_unique($colors);
        sort($colors);
        $colors = implode(',', $colors);

        $cresult   = get_categories(array(
            'include'  => $colors,
            'taxonomy' => 'color'
        ));
    }

    $return = array(
        'size'     => $sresult,
        'color'    => $cresult,
        'designer' => $dresult
    );


    return $return;

}

Sper că ajută pe cineva.

-J

10 mai 2012 20:37:20
3

Iartă-mă dacă am omis ceva, dar nu ar fi la fel de simplu ca:

if (is_object_in_term($post->ID, 'region', 'rotterdam'))
    the_category(); // afișează categoriile asociate articolului curent

În panoul de administrare, atașezi articolul atât la 'pizzerii' cât și la 'mâncare' (bifând ambele casete), sau doar la 'pizzerii'?

Dacă este al doilea caz, the_category() nu va afișa 'Mâncare' în mod implicit, așa că va trebui să obții ierarhia categoriilor manual.

6 dec. 2010 12:52:03
Comentarii

Nu, intenția este de a afișa o listă de categorii, dar doar acele categorii care au postări în care taxonomia personalizată region este setată la Rotterdam. Apropo, această întrebare a fost pusă și pe SO.

Jan Fabry Jan Fabry
6 dec. 2010 13:28:48

Dacă nu înțeleg greșit, acesta pare un răspuns potrivit. Dacă Mamma Mia este pizzeria în Rotterdam, atunci prin definiție există pizzerii în Rotterdam și categoria ar trebui afișată. Altfel, nu înțeleg cum ar trebui să fie conectată categoria la regiune.

Rarst Rarst
6 dec. 2010 14:11:16

@Rarst: Modul în care am înțeles întrebarea este că lista de categorii nu ar trebui afișată doar pe o pagină de postare, ci de exemplu pe region/rotterdam/: pentru toate postările care folosesc acest termen de taxonomie personalizată, afișează-mi un arbore cu toate categoriile la care sunt atașate. OP folosește get_categories(), care nu este limitat la categoriile postării curente.

Jan Fabry Jan Fabry
6 dec. 2010 14:48:05
2

poți obține taxonomiile pentru postări personalizate cu o mică funcție:

    function get_the_taxonomy( $taxonomy, $id = FALSE ) {
        global $post;

        $id = (int) $id;
        if ( !$id )
            $id = (int) $post->ID;

        $categories = get_object_term_cache( $id, $taxonomy );
        if ( FALSE === $categories ) {
            $categories = wp_get_object_terms( $id, $taxonomy );
            wp_cache_add($id, $categories, $taxonomy . '_relationships');
        }

        if ( !empty( $categories ) )
            usort( $categories, '_usort_terms_by_name' );
        else
            $categories = array();

        foreach ( (array) array_keys( $categories ) as $key ) {
            _make_cat_compat( $categories[$key] );
        }

        return $categories;
    }

De asemenea, poți folosi funcția din wp-core:

$taxonomys = get_the_term_list($id, YOUR_CUSTOM_POST_TYPE, '', ', ', '' );

și poți verifica existența unei taxonomii cu is_tax(), vezi codex pentru acest tag condițional

Poate te ajută, dacă am înțeles corect problema ta. Scuze pentru engleza mea proastă.

7 dec. 2010 00:14:21
Comentarii

Cred că Henk Jan dorește să obțină o listă de categorii, independent de un articol curent. Pur și simplu toate categoriile care au articole atribuite termenului personalizat rotterdam.

Jan Fabry Jan Fabry
7 dec. 2010 00:41:47

Mulțumesc pentru sugestie; cred că este posibil să folosim o interogare personalizată cu termenul personalizat. Postarea returnează toți termenii, iar interogarea trebuie să folosească toți sau primul termen pentru a lista în buclă toate articolele legate de acest termen. De asemenea, este posibil să returnăm toate categoriile pentru articolele din această interogare.

bueltge bueltge
7 dec. 2010 10:11:19
4

Vă mulțumesc tuturor pentru ajutor - este foarte apreciat. Doresc să vă împărtășesc soluția la care am ajuns. Știu că nu este cea mai inteligentă soluție. Dezavantajul este că o categorie părinte este afișată pentru o regiune, atunci când nu există niciun post personalizat atașat pentru acea regiune (dar există un post personalizat atașat pentru o altă regiune).

Folosesc acest cod pe o pagină de regiune (arhivă de taxonomie).

<?php
$categories = get_categories();
foreach ($categories as $cat)
{
    if($cat->parent < 1)
    {
        $cat_name = $cat->cat_name;                         
        $catid = get_cat_ID( $cat_name );

        echo '<div class="indexcolumn-top">';

        $img = $taxonomy_images_plugin->get_image_html( 'fullsize', $cat->term_taxonomy_id );
        if( !empty( $img ) )
            print $img;
        else 
            echo '<h2>' .$cat_name. '</h2>';

        $input = array();
        $args=array(
          'child_of' => $catid,
          'orderby' => 'name',
          'order' => 'ASC'
          );

        $categories = get_categories($args);
        foreach ($categories as $cat)
        {
            $cat_name = $cat->cat_name;
            $catid = get_cat_ID( $cat_name );

            $args = array(
                'post_status' => 'publish',
                'taxonomy_name' => 'region',
                'taxonomy_term' => $name,
            );
            $custom_posts = get_posts_by_taxonomy($args);
            if ($custom_posts):
                foreach ($custom_posts as $post):
                    setup_postdata($post);
                    $postcategory = get_the_category(); $postcat = $postcategory[0]->cat_name;
                    if ($postcat == $cat_name):
                        $category = get_the_category(); 
                        $input[] = $catid;
                    endif;
                endforeach;
            endif;
        }
        echo '<br/>';
        $output = array_unique($input);
        if (empty($output)):
            echo '<p>Niciun companie</p>';
            echo '</div>';
        else :
            echo '<ul class="port-box">';
            foreach ($output as $output) {
                $cat_name = get_cat_name($output);  
                echo '<li><a href="' . get_category_link($output) . '" title="' . sprintf( __( "Vezi toate postările din %s" ), $cat_name ) . '" ' . '>' . $cat_name .'</a></li>';                             
            }
            echo '</ul></div>';
        endif;
    }                                                   
}
?>
8 dec. 2010 12:09:53
Comentarii

Nu cred că aceasta este o modalitate eficientă de a face acest lucru: faci multe interogări și nu înțeleg bucla interioară a postărilor: dacă o postare este găsită în categoria curentă, probabil că poți doar să adaugi acea categorie la listă fără a parcurge toate postările?

Jan Fabry Jan Fabry
8 dec. 2010 14:58:14

@Jan: Știu că nu este cea mai inteligentă soluție. Totuși, nu înțeleg remarca ta despre bucla interioară a postărilor. Ai nevoie de bucla interioară pentru a găsi o potrivire - sau nu. Sau, poți întrerupe bucla în caz de potrivire? Dar, cum ai face asta atunci?

Henk Jan Henk Jan
8 dec. 2010 16:32:17

Nu contează, am crezut că funcția ta get_posts_by_taxonomy() selectează atât după taxonomie cât și după categorie. Următoarea întrebare este de ce repeți această interogare iar și iar, în loc să o faci o singură dată și să reutilizezi rezultatele. Și de ce verifici doar prima categorie? Dacă o afacere se află atât în Pizzeria cât și în French Fries, doar una dintre ele va fi returnată, deci ai putea să ratezi una în final.

Jan Fabry Jan Fabry
8 dec. 2010 16:45:43

@Jan: OK. Verific doar prima categorie deoarece afacerile mele pot fi într-o singură categorie. Nu înțeleg prima ta întrebare. if ($custom_posts): endif; poate fi eliminat. Dar, va trebui să faci o buclă pentru a găsi o potrivire - sau nu. Ce înțelegi prin reutilizare?

Henk Jan Henk Jan
8 dec. 2010 17:20:20
0
<?php $cat_id = $_GET["cat"];?>     
      <li id="category-active"><a><?php if ($cat_id){echo get_the_category_by_id($li_id);}else{ echo "Categorie selectată";}?></a></li>            <?php   $subcategories1 = wp_list_categories("title_li&child_of=$cat_id&hide_empty");
                wp_list_categories("title_li=&current_category="); ?>
                    </ul><?php ?>

mulțumesc pentru ajutor.

dar cred că nu este nevoie de foreach sau vreun loop, putem obține subcategoriile oricărei categorii folosind acest cod simplu. Mai întâi $li_id obține ID-ul categoriei curente și îl pasăm dinamic la child_of=$cat_id și afișează subcategoriile categoriei selectate. Eu îl folosesc în bara laterală a site-ului meu.

18 ian. 2011 18:58:37