Filtrare get_categories() per termine di tassonomia in WordPress
Voglio mostrare una categoria solo se un post (personalizzato) è in quella categoria E la regione = $name per quel post.
Esempio: ho un post personalizzato (tipo "business") chiamato "Mamma Mia" nella sottocategoria: "pizzerie" (e nella categoria genitore "cibo"), e nella regione "Rotterdam" (tassonomia personalizzata: "region", termine di tassonomia: "rotterdam").
=> visualizzare la categoria "pizzerie" (e la categoria genitore "cibo")
Il problema è che non ho idea di come realizzarlo. Gradirei qualsiasi aiuto per risolvere questo puzzle.
<?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( __( "Visualizza tutti i post in %s" ), $category->name ) . '" ' . '>' . $category->name.'</a><br/>';
}
}
}
// print_r($categories);
?>
l'intenzione è mostrare un elenco di categorie, ma solo quelle categorie che hanno post in cui la tassonomia personalizzata "region" è impostata su Rotterdam
Questo viene fatto nel plugin Query Multiple Taxonomies:
http://plugins.trac.wordpress.org/browser/query-multiple-taxonomies/trunk/core.php?rev=308185#L10

E più specificamente, nel suo widget di navigazione a discesa. Ottimo! Ora questo dovrebbe solo essere esteso per mostrare anche le categorie genitore: se un post è associato a Pizzerie
lo vedo anche quando navigo in Cibo
, ma Cibo
non viene mostrato nel widget se il post non è esplicitamente associato ad esso.

Idea generale - eseguire una query per un insieme specifico di post, raccogliere tutte le loro categorie, filtrarle e lasciare che la funzione le organizzi.
Codice generico:
$posts = get_posts(array(
'tag' => 'linux'
));
$categories = array();
foreach( $posts as $post ) {
$cats = get_the_category($post->ID);
foreach($cats as $c)
$categories[] = $c->term_id;
}
$categories = array_unique($categories);
sort($categories);
$categories = implode(',', $categories);
$result = get_categories(array(
'include' => $categories
));
I problemi sono - per quanto ricordo, query decenti per tassonomie multiple arriveranno solo in WP 3.1 e questo potrebbe diventare molto intensivo, quindi richiederà caching (probabilmente per ogni region
).

Come influisce il parametro include
sui risultati gerarchici? Se ci sono alcuni post in Pizzerie
, ma nessuno direttamente collegato al suo genitore Cibo
, verrà visualizzato Cibo
? Oppure i post vengono automaticamente collegati anche alle categorie genitore?

@Jan Fabry ho testato, se viene passato solo l'id della categoria figlia a get_categories()
allora la categoria genitore non viene recuperata. :( Quindi un altro passaggio sarebbe quello di scorrere le categorie e ottenere i genitori. Un disastro ancora più grande.

Sulla versione di WordPress che sto utilizzando, ovvero la versione 3.1.2. Se aggiungi 'taxonomy' => 'taxonomy_term' all'array degli argomenti, dovrebbe funzionare. Quindi ecco una modifica al tuo codice originale per includere la tassonomia nell'array. Non so però il nome della tassonomia che stai cercando di utilizzare o meno:
<?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( __( "Visualizza tutti i post in %s" ), $category->name ) . '" ' . '>' . $category->name.'</a><br/>';
}
}
}
// print_r($categories);
?>

Ho adattato la risposta di @rarst sopra menzionata per utilizzare 3 tassonomie personalizzate. Voglio solo visualizzare i termini che sono associati a uno o più post nel loop.
Ecco la mia funzione che ho aggiunto a 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;
}
Spero che questo possa aiutare qualcun altro.
-J

Perdonami se mi è sfuggito qualcosa, ma non sarebbe semplice come:
if (is_object_in_term($post->ID, 'region', 'rotterdam'))
the_category(); // mostra le categorie associate al post corrente
Nell'amministrazione, stai assegnando il post sia a 'pizzerie' che a 'cibo' (selezionando entrambe le caselle), o solo a 'pizzerie'?
Se quest'ultimo, the_category()
non mostrerà 'Cibo' di default, quindi dovrai recuperare la gerarchia delle categorie manualmente.

No, l'intenzione è mostrare un elenco di categorie, ma solo quelle categorie che hanno post in cui la tassonomia personalizzata region
è impostata su Rotterdam
. Questa domanda è stata posta anche su SO, tra l'altro.

A meno che non stia fraintendendo, questa sembra una risposta adeguata. Se Mamma Mia
è una pizzeria
a rotterdam
, allora per definizione ci sono pizzerie a Rotterdam e la categoria dovrebbe essere visualizzata. Altrimenti non capisco come la categoria dovrebbe essere collegata alla regione.

@Rarst: Il modo in cui ho interpretato la domanda è che l'elenco delle categorie non dovrebbe essere mostrato solo sulla pagina di un post, ma ad esempio su region/rotterdam/
: per tutti i post che utilizzano questo termine di tassonomia personalizzata, restituiscimi un albero di tutte le categorie a cui sono collegati. L'OP utilizza get_categories()
, che non è limitato alle categorie del post corrente.

puoi ottenere le tassonomie per un custom post con una piccola funzione:
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;
}
Puoi anche utilizzare la funzione wp-core:
$taxonomys = get_the_term_list($id, YOUR_CUSTOM_POST_TYPE, '', ', ', '' );
e puoi verificare una tassonomia con is_tax()
, vedi codex per questo conditional tag
Forse questo può aiutare, se ho capito bene il tuo problema. Scusa per il mio inglese non perfetto.

Penso che Henk Jan voglia ottenere un elenco di categorie, indipendenti da un post corrente. Solo tutte le categorie che hanno post assegnati al termine personalizzato rotterdam
.

Grazie per il suggerimento; penso sia possibile utilizzare una query personalizzata con il termine personalizzato. Il post restituisce tutti i termini, e la query deve utilizzare tutti o il primo termine per elencare nel loop tutti i post relativi a questo termine. È anche possibile restituire tutte le categorie dei post in questa query.

Grazie a tutti per l'aiuto - è davvero fantastico. Vorrei condividere con voi la soluzione a cui sono arrivato. So che non è la soluzione più intelligente. Lo svantaggio è che viene mostrata una categoria genitore per una regione, quando non ci sono post personalizzati associati ad essa per questa regione (ma c'è un post personalizzato associato per un'altra regione).
Sto utilizzando questo codice in una pagina di archivio tassonomia per le regioni.
<?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>Nessuna azienda</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( __( "Visualizza tutti i post in %s" ), $cat_name ) . '" ' . '>' . $cat_name .'</a></li>';
}
echo '</ul></div>';
endif;
}
}
?>

Non credo sia un modo efficiente per farlo: fai molte query e non capisco il ciclo interno dei post: se un post viene trovato nella categoria corrente, probabilmente puoi semplicemente aggiungere quella categoria alla lista senza ciclare attraverso tutti i post?

@Jan: So che non è la soluzione più intelligente. Però non capisco la tua osservazione sul ciclo interno dei post. Avrai bisogno del ciclo interno dei post per trovare una corrispondenza - oppure no. Oppure, puoi interrompere il ciclo in caso di corrispondenza? Ma come faresti allora?

Non importa, pensavo che la tua funzione get_posts_by_taxonomy()
selezionasse sia per tassonomia che per categoria. La domanda successiva è perché ripeti questa query più e più volte, invece di farla una volta e riutilizzare i risultati. E perché controlli solo la prima categoria? Se un'attività è sia in Pizzeria
che in French Fries
, ne verrà restituita solo una, quindi potresti perderne una alla fine.

@Jan: OK. Sto controllando solo la prima categoria perché le mie attività possono essere in una sola categoria. Non capisco la tua prima domanda. Il codice if ($custom_posts): endif; può essere rimosso. Ma dovrai fare un loop per trovare una corrispondenza - oppure no. Cosa intendi con riutilizzo?

<?php $cat_id = $_GET["cat"];?>
<li id="category-active"><a><?php if ($cat_id){echo get_the_category_by_id($li_id);}else{ echo "Categoria selezionata";}?></a></li> <?php $subcategories1 = wp_list_categories("title_li&child_of=$cat_id&hide_empty");
wp_list_categories("title_li=¤t_category="); ?>
</ul><?php ?>
grazie per il tuo aiuto.
ma penso non ci sia bisogno di foreach o qualsiasi loop, possiamo ottenere i figli di qualsiasi categoria usando questo semplice codice: prima $li_id
ottiene l'ID della categoria corrente e lo passiamo dinamicamente a child_of=$cat_id
e mostra i figli della categoria selezionata. Lo sto usando nella sidebar del mio sito.
