Filtrare get_categories() pentru termen de taxonomie în WordPress
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);
?>
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

Ș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.

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

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 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.

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

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

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.

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.

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: 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.

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ă.

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
.

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.

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;
}
}
?>

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: Ș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?

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.

<?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=¤t_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.
