Aggiungere un Filtro Tassonomia alla Lista Admin per un Custom Post Type

19 ago 2010, 18:13:29
Visualizzazioni: 108K
Voti: 139

Ho creato un Custom Post Type chiamato 'listing' e aggiunto una Tassonomia Personalizzata chiamata 'businesses'. Vorrei aggiungere un menu a tendina delle Attività alla lista amministrativa dei Listings.

Ecco come appare questa funzionalità nella lista amministrativa degli Articoli (vorrei lo stesso per il mio Custom Post Type):

Menu a tendina Categorie negli Articoli

Ecco il mio codice attuale (E qui lo stesso codice su Gist.):

Per aggiungere il filtro dropdown, devi aggiungere questa funzione al tuo codice esistente all'interno della classe Listing:

function restrict_listings_by_business() {
    global $typenow;
    $post_type = 'listing'; // Il tuo custom post type
    $taxonomy  = 'businesses'; // La tua tassonomia
    
    if ($typenow == $post_type) {
        $selected      = isset($_GET[$taxonomy]) ? $_GET[$taxonomy] : '';
        $info_taxonomy = get_taxonomy($taxonomy);
        
        wp_dropdown_categories(array(
            'show_option_all' => __("Mostra tutte {$info_taxonomy->label}"),
            'taxonomy'        => $taxonomy,
            'name'           => $taxonomy,
            'orderby'        => 'name',
            'selected'       => $selected,
            'show_count'     => true,
            'hide_empty'     => true,
        ));
    }
}

Poi, aggiungi questa riga nel costruttore della classe (funzione Listing()) dopo la registrazione delle tassonomie:

add_action('restrict_manage_posts', array(&$this, 'restrict_listings_by_business'));

Infine, aggiungi questa funzione per convertire l'ID della tassonomia nel suo slug quando viene utilizzato il filtro:

function convert_business_id_to_slug($query) {
    global $pagenow;
    $post_type = 'listing'; // Il tuo custom post type
    $taxonomy  = 'businesses'; // La tua tassonomia
    $q_vars    = &$query->query_vars;
    
    if ($pagenow == 'edit.php' && isset($q_vars['post_type']) && $q_vars['post_type'] == $post_type && isset($_GET[$taxonomy]) && is_numeric($_GET[$taxonomy]) && $_GET[$taxonomy] != 0) {
        $term = get_term_by('id', $_GET[$taxonomy], $taxonomy);
        $q_vars[$taxonomy] = $term->slug;
    }
}

E aggiungi questa riga nel costruttore:

add_filter('parse_query', array(&$this, 'convert_business_id_to_slug'));
2
Commenti

Grazie per lo screenshot, davvero utile averli.

MikeSchinkel MikeSchinkel
19 ago 2010 20:29:13

C'è un plugin Admin Taxonomy Filter che può fare esattamente questo lavoro.

Anh Tran Anh Tran
20 set 2017 04:33:05
Tutte le risposte alla domanda 17
11
150

AGGIORNAMENTO Luglio 2024:

Questo codice non funziona più. Testato nella versione corrente di WP al momento della scrittura (6.5.5). Per farlo funzionare nuovamente, sono necessarie alcune modifiche al codice del Passo 1:

Parametro name

In wp_dropdown_categories() il parametro name deve essere lo slug della tassonomia. Quindi, anche se in questo caso non cambia, non è del tutto ovvio cosa dovrebbero cambiare gli altri. Soprattutto perché la documentazione ufficiale non lo menziona:

name string

Valore per l'attributo 'name' dell'elemento select. Predefinito 'cat'.

Questo potrebbe far pensare che sia una stringa personalizzata come "my_select_name". Per evitare confusione, possiamo semplicemente usare la variabile.

wp_dropdown_categories(array(
   'name' => $taxonomy,
    ...
));

Parametro selected

Il parametro selected deve essere modificato in:

wp_dropdown_categories(array(
   'selected' => $wp_query->query_vars['term']?? 0,
    ...
));

Questo perché il term è definito in query_vars invece che in query. Se il termine non esiste in query_vars, molto probabilmente non è stato selezionato alcun termine, quindi possiamo usare l'operatore di coalescenza nulla per verificarlo e se è null|undefined allora selezioniamo semplicemente l'opzione "mostra tutto" con il valore 0.

Parametro value_field

Un nuovo parametro è stato aggiunto in WP 4.2.0: value_field.

Utilizzando questo parametro, possiamo ora dire a WP di utilizzare un "campo del termine" specifico per popolare i valori delle opzioni. Dalla documentazione:

value_field string

Campo del termine che dovrebbe essere utilizzato per popolare l'attributo 'value' degli elementi option. Accetta qualsiasi campo valido del termine: 'term_id', 'name', 'slug', 'term_group', 'term_taxonomy_id', 'taxonomy', 'description', 'parent', 'count'. Predefinito 'term_id'.

Aggiungere slug a questo parametro popolerà i valori delle opzioni con gli slug dei termini. Poiché lo slug è necessario per il funzionamento della funzione di filtro, questo parametro fa sì che i filtri funzionino solo dal codice del Passo 1 senza la necessità del Passo 2.

Quindi il Passo 2 può essere ignorato se si utilizza value_field.

wp_dropdown_categories(array(
   'value_field' => 'slug',
    ...
));

Ho lasciato il codice originale qui sotto, quindi apporta queste modifiche come dettagliato sopra al codice qui sotto.



AGGIORNAMENTO: Ho incluso una nuova risposta completa ma ho comunque lasciato la mia risposta originale in fondo a cui fanno riferimento i primi commenti.


Ciao @tarasm:

Anche se ho detto che non dovrebbe essere difficile, è un po' complesso. Ma prima di approfondire il codice...

Le schermate:

...diamo un'occhiata ad alcune schermate del prodotto finito:

Pagina elenco annunci senza filtri:

Pagina elenco annunci senza filtri
(fonte: mikeschinkel.com)

Pagina elenco annunci con filtri:

Pagina elenco annunci con filtri
(fonte: mikeschinkel.com)

Il codice

Ecco qui... (Nota: Ho usato la forma singolare per il nome della tassonomia business; spero che corrisponda al tuo. Da molta esperienza sia con WordPress che con lo sviluppo di database in passato, credo che sia meglio fare così.)

Passo #1: L'hook restrict_manage_posts.

La prima cosa da fare è agganciare l'azione restrict_manage_posts che non ha parametri ed è chiamata da /wp-admin/edit.php (in v3.0.1 quella chiamata è alla riga 378.) Questo ti permetterà di generare il menu a tendina select nella posizione appropriata sopra l'elenco degli annunci.

<?php
add_action('restrict_manage_posts','restrict_listings_by_business');
function restrict_listings_by_business() {
    global $typenow;
    global $wp_query;
    if ($typenow=='listing') {
        $taxonomy = 'business';
        $business_taxonomy = get_taxonomy($taxonomy);
        wp_dropdown_categories(array(
            'show_option_all' =>  __("Mostra tutti {$business_taxonomy->label}"),
            'taxonomy'        =>  $taxonomy,
            'name'            =>  'business',
            'orderby'         =>  'name',
            'selected'        =>  $wp_query->query['term'],
            'hierarchical'    =>  true,
            'depth'           =>  3,
            'show_count'      =>  true, // Mostra # annunci tra parentesi
            'hide_empty'      =>  true, // Non mostrare attività senza annunci
        ));
    }
}

Iniziamo controllando la variabile $typenow per assicurarci che siamo effettivamente su un post_type di tipo listing. Se non lo fai, otterrai questo menu a tendina per tutti i tipi di post, che in alcuni casi è quello che vuoi, ma non in questo caso.

Successivamente carichiamo le informazioni sulla tassonomia business usando get_taxonomy(). Ne abbiamo bisogno per recuperare l'etichetta per la tassonomia (cioè "Business"; avremmo potuto hard-codarla, ma non è molto buono se poi devi internazionalizzare). Poi chiamiamo wp_dropdown_categories() con tutti gli argomenti appropriati nell'array $args per generare il menu a tendina

<?php
return wp_dropdown_categories(array(
    'show_option_all' =>  __("Mostra tutti {$business_taxonomy->label}"),
    'taxonomy'        =>  $taxonomy,
    'name'            =>  'business',
    'orderby'         =>  'name',
    'selected'        =>  $wp_query->query['term'],
    'hierarchical'    =>  true,
    'depth'           =>  3,
    'show_count'      =>  true, // Mostra # annunci tra parentesi
    'hide_empty'      =>  true, // Non mostrare attività senza annunci
));

Ma quali sono gli argomenti appropriati? Vediamoli uno per uno:

  • show_optional_all - Abbastanza semplice, è ciò che viene visualizzato nel menu a tendina all'inizio e quando non è stato applicato alcun filtro. Nel nostro caso sarà "Mostra tutti i Business" ma avremmo potuto chiamarlo "Annunci per tutti i Business" o qualsiasi altra cosa ti piaccia.

  • taxonomy - Questo argomento dice alla funzione da quale tassonomia recuperare i termini anche se la funzione ha categories nel nome. Nella v2.8 e precedenti WordPress non aveva tassonomie personalizzate ma quando sono state aggiunte il team ha deciso che sarebbe stato più semplice aggiungere un argomento taxonomy a questa funzione piuttosto che crearne un'altra con un altro nome.

  • name - Questo argomento ti permette di specificare il valore che WordPress utilizzerà per l'attributo name dell'elemento <select> generato per il menu a tendina. Nel caso non fosse ovvio, questo è anche il valore che verrà utilizzato nell'URL durante il filtraggio.

  • orderby - Questo argomento dice a WordPress come ordinare i risultati alfabeticamente. Nel nostro caso abbiamo specificato di ordinare per il name dei termini nella tassonomia, cioè i nomi dei business in questo caso.

  • selected - Questo argomento è necessario per far sì che il menu a tendina mostri il filtro corrente nel menu a tendina. Dovrebbe essere il term_id del termine della tassonomia selezionato. Nel nostro caso potrebbe essere il term_id di "Business #2". Dove otteniamo questo valore? Dalla variabile globale di WordPress $wp_query; ha una proprietà query che contiene un array di tutti i parametri URL e i loro valori (a meno che qualche plugin indisciplinato non l'abbia già modificato, ovviamente). Dato come WordPress elabora le cose, ci sarà un parametro URL term passato nell'URL quando l'utente clicca sul pulsante filtro se l'utente ha selezionato un termine valido (cioè uno dei business elencati).

  • hierarchical - Impostando questo su true dici alla funzione di rispettare la natura gerarchica della tassonomia e di visualizzarli in una vista ad albero se i termini (business) hanno effettivamente figli. Per una schermata per vedere come appare, vedi sotto.

  • depth - Questo argomento collabora con l'argomento hierarchical per determinare quanti livelli di profondità la funzione dovrebbe andare nel visualizzare i figli.

  • show_count - Se true questo argomento visualizzerà un conteggio dei post tra parentesi a sinistra del nome del termine all'interno del menu a tendina. In questo caso visualizzerebbe un conteggio degli annunci associati a un business. Per una schermata per vedere come appare, vedi sotto.

  • hide_empty - Infine, se ci sono termini nella tassonomia che non sono associati a un post (cioè business non associati a un annuncio) impostando questo su true li escluderà dall'essere inclusi nel menu a tendina.

Menu a tendina della tassonomia con gerarchia e conteggi
(fonte: mikeschinkel.com)

Passo #2: L'hook parse_query.

Successivamente rivolgiamo la nostra attenzione all'hook parse_query che ha un parametro ($query) ed è chiamato da /wp-includes/query.php (in v3.0.1 quella chiamata è alla riga 1549.) Viene chiamato quando WordPress ha finito di ispezionare l'URL e di impostare tutti i valori appropriati nell'attuale $wp_query inclusi elementi come $wp_query->is_home e $wp_query->is_author, ecc.

Dopo che l'hook parse_query viene eseguito, WordPress chiamerà get_posts() e caricherà un elenco di post in base a quanto specificato nell'attuale $wp_query. Quindi parse_query è spesso un ottimo posto per far cambiare idea a WordPress su quali post caricare.

Nel tuo caso d'uso vogliamo che WordPress filtri in base ai business selezionati; cioè visualizzare solo quegli Annunci che sono stati associati al business selezionato (direi "...solo quegli Annunci che sono stati "categorizzati" dal business selezionato" ma tecnicamente non è corretto; category è la sua tassonomia alla pari con business tranne che category è integrato in WordPress e business è personalizzato. Ma per chi ha familiarità con la categorizzazione dei post questo può aiutare a capire poiché funzionano quasi allo stesso modo. Ma sto divagando...)

Passiamo al codice. La prima cosa che facciamo è prendere un riferimento all'array query_vars dell'attuale $wp_query in modo che sia più comodo lavorarci, proprio come viene fatto nella funzione parse_query() di WordPress. A differenza di $wp_query->query che viene utilizzato per rispecchiare i parametri passati nell'URL, l'array $wp_query->query_vars viene utilizzato per controllare la query che WordPress esegue e ci si aspetta che venga modificato. Quindi, se devi modificare uno, sarebbe questo (almeno penso che questa sia la differenza tra i due; se qualcuno sa diversamente per favore fammelo sapere così posso aggiornarlo!)

<?php
add_filter('parse_query','convert_business_id_to_taxonomy_term_in_query');
function convert_business_id_to_taxonomy_term_in_query($query) {
    global $pagenow;
    $qv = &$query->query_vars;
    if ($pagenow=='edit.php' &&
            isset($qv['taxonomy']) && $qv['taxonomy']=='business' &&
            isset($qv['term']) && is_numeric($qv['term'])) {
        $term = get_term_by('id',$qv['term'],'business');
        $qv['term'] = $term->slug;
    }
}

Successivamente testiamo $pagenow per assicurarci che stiamo effettivamente caricando WordPress dal percorso URL /wp-admin/edit.php. Lo facciamo per evitare di modificare accidentalmente query su altre pagine. Verifichiamo anche di avere sia business come elemento taxonomy che un elemento term. (Nota taxonomy e term sono una coppia; vengono usati insieme per permettere l'interrogazione di un termine della tassonomia; devi avere entrambi o WordPress non sa quale tassonomia ispezionare.)

Potresti chiederti come business sia finito nell'elemento taxonomy dell'array query_vars. Ciò che abbiamo scritto nel nostro hook parse_query ha attivato la magia interna di WordPress che era in attesa quando hai registrato la tassonomia "business" impostando query_var su true (register_taxonomy() copia il nome della tassonomia come suo query_var; puoi cambiarlo ovviamente ma a meno che non hai un conflitto è meglio attenersi allo stesso):

<?php
add_action('init','register_business_taxonomy');
    function register_business_taxonomy() {
        register_taxonomy('business',array('listing'),array(
        'label' => 'Business',
        'public'=>true,
        'hierarchical'=>true,
        'show_ui'=>true,
        'query_var'=>true
    ));
}

Ora $wp_query di WordPress è stato scritto per usare gli slug per le query filtrate standard della tassonomia, non gli ID dei termini della tassonomia. Per questo caso d'uso ciò di cui abbiamo realmente bisogno per far funzionare la nostra query di filtraggio sono questi:

taxonomy: business

term: business-1 (cioè lo slug)

Non questi:

taxonomy: business

term: 27 (cioè il term_id)

Curiosamente e purtroppo il menu a tendina generato da wp_dropdown_categories() imposta l'attributo value dell'<option> all'term_id del termine (/business), non lo slug del termine. Quindi dobbiamo convertire $wp_query->query_vars['term'] da un term_id numerico al suo slug stringa come segue nello snippet preso da sopra (Nota questo non è il modo più performante per interrogare un database ma finché WordPress non aggiunge il supporto per gli term_id nella sua query questo è il meglio che possiamo fare!):

<?php
$term = get_term_by('id',$qv['term'],'business');
$qv['term'] = $term->slug;

E questo è tutto! Con queste due funzioni ottieni il filtraggio che desideri.

MA ASPETTA, C'È DI PIÙ! :-)

Ho aggiunto una colonna "Business" al tuo elenco Annunci perché, beh, sapevo che sarebbe stata la tua prossima domanda. Senza avere una colonna per ciò che filtri può essere molto confuso per l'utente finale. (Ho avuto difficoltà anch'io, e sono il programmatore!) Puoi già vedere la colonna "Business" nelle schermate precedenti sopra.

Passo #3: L'hook manage_posts_columns.

Per aggiungere una colonna all'elenco dei post sono necessari altri due (2) hook. Il primo è manage_posts_columns o la versione specifica per il tipo di post manage_listing_posts_columns che ho chiamato invece. Accetta un parametro (posts_columns) ed è chiamato da /wp-admin/includes/template.php (in v3.0.1 quella chiamata è alla riga 623):

<?php
add_action('manage_listing_posts_columns', 'add_businesses_column_to_listing_list');
function add_businesses_column_to_listing_list( $posts_columns ) {
    if (!isset($posts_columns['author'])) {
        $new_posts_columns = $posts_columns;
    } else {
        $new_posts_columns = array();
        $index = 0;
        foreach($posts_columns as $key => $posts_column) {
            if ($key=='author')
                $new_posts_columns['businesses'] = null;
            $new_posts_columns[$key] = $posts_column;
        }
    }
    $new_posts_columns['businesses'] = 'Business';
    return $new_posts_columns;
}

La tua funzione hook manage_posts_columns riceve un array di colonne dove il valore è l'intestazione della colonna visualizzata e la chiave è l'identificatore interno della colonna. Gli identificatori di colonna standard possono includere questi e altri: 'cb', 'title', 'author', ``'date'`, ecc.

'cb', è la colonna checkbox e sia 'title' che 'date' si riferiscono rispettivamente a post_title e post_date dalla tabella wp_posts, rispettivamente. 'author' ovviamente è il campo post_author dopo che il nome dell'autore è stato recuperato dalla tabella wp_users.

Schermata della colonna 'cb' dei post come checkbox.
(fonte: mikeschinkel.com)

Per l'hook manage_posts_columns vogliamo semplicemente inserire la nostra colonna businesses nell'array $posts_columns prima di 'author', assumendo che qualche altro plugin non abbia già rimosso author dall'elenco!

$new_posts_columns['businesses'] = 'Business';

(Nota mentre scrivevo add_businesses_column_to_listing_list() mi è venuto in mente che PHP deve avere un modo più semplice per inserire un valore in un array associativo nell'ordine corretto?!? O almeno ci deve essere una funzione nel core di WordPress per farlo? Ma visto che Google mi ha deluso sono andato con ciò che funziona. Se qualcuno ha suggerimenti alternativi sarò tutto orecchie e grato in anticipo!)

Il che finalmente ci porta a...

Passo #4: L'hook manage_posts_custom_column

La seconda cosa delle due (2) che dobbiamo fare per far sì che i nostri business vengano visualizzati nella colonna è effettivamente emettere il nome di ciascuno dei business associati utilizzando l'hook manage_posts_custom_column. Questo hook accetta due (2) parametri (column_id e post_id) ed è anche chiamato da /wp-admin/includes/template.php (in v3.0.1 quella chiamata è alla riga 1459.):

<?php
add_action('manage_posts_custom_column', 'show_businesses_column_for_listing_list',10,2);
function show_businesses_column_for_listing_list( $column_id,$post_id ) {
    global $typenow;
    if ($typenow=='listing') {
        $taxonomy = 'business';
        switch ($column_name) {
        case 'businesses':
            $businesses = get_the_terms($post_id,$taxonomy);
            if (is_array($businesses)) {
                foreach($businesses as $key => $business) {
                    $edit_link = get_term_link($business,$taxonomy);
                    $businesses[$key] = '<a href="'.$edit_link.'">' . $business->name . '</a>';
                }
                //echo implode("<br/>",$businesses);
                echo implode(' | ',$businesses);
            }
            break;
        }
    }
}

Questo hook viene chiamato per ogni colonna per ogni riga di post (/business). Prima verifichiamo che stiamo effettivamente lavorando solo con il tipo di post personalizzato listing e poi usiamo un'istruzione switch per testare contro il column_id. Ho scelto switch perché questo hook è spesso usato per generare output per molte colonne diverse, specialmente se usiamo una funzione per molti tipi di post diversi che potrebbe assomigliare a questo:

<?php
add_action('manage_posts_custom_column', 'my_manage_posts_custom_column',10,2);
function my_manage_posts_custom_column( $column_id,$post_id ) {
    global $typenow;
    switch ("{$typenow}:{$column_id}") {
    case 'listing:business':
        echo '...qualunque cosa...';
        break;
    case 'listing:property':
        echo '...qualunque cosa...';
        break;
    case 'agent:listing':
        echo '...qualunque cosa...';
        break;
    }
}

Esaminando il nostro caso d'uso un po' più da vicino vedi la funzione get_the_terms() che semplicemente restituisce l'elenco dei termini per questa tassonomia (cioè i business per questo annuncio). Qui otteniamo il permalink per la pagina front-end del termine che normalmente elenca i post associati al termine ma ovviamente potrebbe essere diverso a seconda del tema e/o dei plugin installati.

Usiamo il permalink per collegare ipertestualmente il termine solo perché mi piace collegare ipertestualmente le cose. Poi uniamo tutti i termini (/business) collegati ipertestualmente insieme separati con il carattere pipe ('|') e lo emettiamo nel buffer PHP che lo invia al browser/client HTTP dell'utente:

<?php
$businesses = get_the_terms($post_id,$taxonomy);
if (is_array($businesses)) {
    foreach($businesses as $key => $business) {
        $edit_link = get_term_link($business,$taxonomy);
        $businesses[$key] = '<a href="'.$edit_link.'">' . $business->name . '</a>';
    }
    //echo implode("<br/>",$businesses);
    echo implode(' | ',$businesses);
}

ORA abbiamo finalmente finito.

Riepilogo

Quindi, in sintesi, devi usare i seguenti quattro (4) hook per ottenere sia un filtro che una colonna correlata nella pagina dell'elenco dei post personalizzati (Oh, funzionerà anche con Articoli e Pagine.) Sono:

  • Passo #1: L'hook restrict_manage_posts.
  • Passo #2: L'hook parse_query.
  • Passo #3: L'hook manage_posts_columns.
  • Passo #4: L'hook manage_posts_custom_column

Dove scaricare il codice

Ma se ti costringessi a leggere tutto quanto sopra allora certamente non sarei una persona molto gentile se ti facessi anche scavare il codice solo per poterlo provare! Ma contrariamente a ciò che dicono alcune persone, sono gentile. Quindi eccoti:

NOTA a @tarasm: Ho incluso hook per un register_post_type() e register_taxonomy() in modo che altri potessero provare questo senza doverli ricreare. Probabilmente vorrai eliminare quelle due chiamate di funzione prima di testarlo.

FINE


Risposta originale:

Ciao @tarasm:

Stai cercando un menu a tendina in alto come in questa schermata o stai cercando un menu a tendina per ogni record di post e in tal caso come ti aspetteresti che quest'ultimo funzioni?

Come creare la funzionalità Ordina per per un Tipo di Post Personalizzato nell'Admin di WordPress
(fonte: mikeschinkel.com)

Se il primo, dai un'occhiata a questa risposta alla domanda Come ordinare l'area admin di un tipo di post personalizzato WordPress per un campo personalizzato? Se è ciò di cui hai bisogno posso fornire maggiori dettagli relativi alla tassonomia.

19 ago 2010 18:58:37
Commenti

Sto cercando un menu a tendina in alto che mostri il filtro per le Categorie. Mi chiedevo se esiste un modo standard per farlo senza dover scrivere codice personalizzato.

Taras Mankovski Taras Mankovski
19 ago 2010 20:04:44

A prima vista non credo si possa fare senza codice personalizzato, ma d'altra parte non penso che il codice personalizzato debba essere particolarmente complesso. Ho però una chiamata con un cliente da preparare, quindi dovrò rimandare a più tardi oggi.

MikeSchinkel MikeSchinkel
19 ago 2010 20:30:05

In realtà entrambe le soluzioni (somatic e MikeSchinkel) non funzionano quando si cerca di filtrare 2 diverse tassonomie con lo stesso filtro :-/

Filtra sempre solo l'ultima tassonomia quando si provano a filtrare 2+ contemporaneamente.

Ünsal Korkmaz Ünsal Korkmaz
3 nov 2010 05:24:09

@Ünsal L'attuale versione di WordPress (3.0) non supporta query multiple su Taxonomy, ma da quello che ho sentito questo cambierà con la versione 3.1. Per far funzionare questo esempio con più taxonomy, dovresti aggiungere alcuni join e condizioni where alla query utilizzando i filter hook Posts_join e posts_where.

Manny Fleurmond Manny Fleurmond
5 gen 2011 18:07:48

grazie per l'ottima risposta - ma c'è un piccolo errore di battitura nell'esempio di codice del passaggio #4: dovrebbe essere $column_id e non column_name. La versione su github è comunque corretta.

Philipp Kyeck Philipp Kyeck
13 nov 2011 19:14:36

In WP 3.1+, i passaggi uno e due sono migliori nella risposta di @drew-gourley (in realtà, il tuo passaggio 2 non ha funzionato per me, penso ci siano dei cambiamenti in questo filtraggio nelle nuove versioni di WordPress).

Tomasz Struczyński Tomasz Struczyński
3 dic 2011 12:10:32

Mike, credo che potresti migliorare la chiarezza di questo (fantastico) tutorial, modificando gli argomenti di wp_dropdown_categories in modo che 'name' => $taxonomy, per rendere ovvio che l'attributo name del campo select deve essere lo slug della tassonomia registrata (o più specificamente, lo slug di query_var). Così com'è, sembra che 'taxonomy' debba essere lo slug della tassonomia, ma 'name' possa essere qualsiasi cosa arbitraria, il che credo non sia proprio il caso, a meno che tu non sia disposto a elaborare manualmente la query string in parse_query

Tom Auger Tom Auger
7 dic 2011 22:38:32

risposta molto brillante e completa, ma non dovresti restituire la variabile $query nella tua funzione convert_business_id_to_taxonomy_term_in_query()?

helgatheviking helgatheviking
8 gen 2012 00:30:22

Mi aggiungo alla lunga lista di complimenti precedenti! Le lezioni di Mike sono (abbastanza spesso) come una lezione all'università... E vorrei far notare a chiunque stia ricercando il problema che la risposta di @DrewGourley qui sotto è oro puro :)

brasofilo brasofilo
9 lug 2012 16:42:28

Una cosa che non è immediatamente chiara è che get_term_link() collegherà all'archivio pubblico di una tassonomia, piuttosto che mostrare i risultati filtrati in WP-Admin. Non sono sicuro se esista una funzione per generare questo link, quindi deve essere creato manualmente, ad esempio: <a href="edit.php?CUSTOM_TAXONOMY=FOO&post_type=CUSTOM_POST_TYPE">TAXONOMY_NAME</a> ma a parte questo piccolo dettaglio, è fantastico!

User User
7 mag 2013 21:34:46

Vorrei far notare che a partire da WordPress v3.5, puoi aggiungere colonne di tassonomia semplicemente aggiungendo 'show_admin_column' => true ai parametri di register_taxonomy.

Luca Reghellin Luca Reghellin
15 set 2017 12:06:14
Mostra i restanti 6 commenti
6
46

Volevo solo condividere un'implementazione alternativa. Quando ho cercato di risolvere questo problema, non avevo a disposizione l'incredibile tutorial di Mike, quindi la mia soluzione è un po' diversa. Nello specifico, semplificherò il passo #1 di Mike ed eliminerò il passo #2 - gli altri passaggi rimangono comunque validi.

Nel tutorial di Mike, l'uso di wp_dropdown_categories() ci evita di costruire manualmente le liste, ma richiede una modifica condizionale complessa della query (passo #2) per gestire il suo utilizzo dell'ID invece dello slug. Senza contare la difficoltà di modificare quel codice per gestire altri scenari, come i filtri multipli per tassonomia.

Un altro approccio è semplicemente non utilizzare affatto il problematico wp_dropdown_categories(), ma invece costruire da zero le nostre liste a discesa. Non è così complicato, richiede meno di 30 righe di codice e non necessita affatto dell'hook parse_query:

add_action( 'restrict_manage_posts', 'my_restrict_manage_posts' );
function my_restrict_manage_posts() {

    // mostra questi filtri di tassonomia solo negli elenchi dei post type desiderati
    global $typenow;
    if ($typenow == 'photos' || $typenow == 'videos') {

        // crea un array di slug di tassonomie che vuoi filtrare - se vuoi recuperare tutte le tassonomie, potresti usare get_taxonomies() per costruire la lista
        $filters = array('plants', 'animals', 'insects');

        foreach ($filters as $tax_slug) {
            // recupera l'oggetto della tassonomia
            $tax_obj = get_taxonomy($tax_slug);
            $tax_name = $tax_obj->labels->name;
            // recupera l'array di oggetti term per tassonomia
            $terms = get_terms($tax_slug);

            // genera l'html per il filtro a discesa della tassonomia
            echo "<select name='$tax_slug' id='$tax_slug' class='postform'>";
            echo "<option value=''>Mostra Tutti $tax_name</option>";
            foreach ($terms as $term) {
                // genera ogni opzione del select, verificando l'ultimo $_GET per mostrare l'opzione corrente selezionata
                echo '<option value='. $term->slug, $_GET[$tax_slug] == $term->slug ? ' selected="selected"' : '','>' . $term->name .' (' . $term->count .')</option>';
            }
            echo "</select>";
        }
    }
}

Semplicemente inserendo le tassonomie desiderate nell'array $filters, puoi generare rapidamente filtri multipli per tassonomia. Appaiono esattamente come quelli negli screenshot di Mike. Poi puoi procedere con i passi #3 e #4.

23 ott 2010 08:00:36
Commenti

@somatic - Bel aggiornamento! Sì, usare wp_dropdown_categories() richiede davvero molte soluzioni alternative. Cerco di attenermi alle funzioni di base quando possibile, ma come fai notare a volte richiede più lavoro in questo modo. Dimostra solo che con WordPress spesso c'è più di un buon modo per risolvere un problema. Ottimo lavoro!

MikeSchinkel MikeSchinkel
23 ott 2010 12:53:41

Ha smesso di funzionare per me su WordPress 3.1. Sto cercando di capire cosa sia cambiato esattamente. Sembra che dovrebbe ancora funzionare: la tassonomia e gli slug dei termini compaiono come valori GET nell'URL, ma il risultato è semplicemente 0 risultati.

Manny Fleurmond Manny Fleurmond
24 feb 2011 08:40:11

Ho provato a farlo funzionare ma l'unico modo in cui sono riuscito è stato usare l'hook parse_query, verificare la query var della tassonomia e impostare le query var della tassonomia e del termine in base a quello. Sto usando WP 3.1. La tassonomia e il termine dovrebbero apparire nell'URL quando viene inviato il filtro?

sanchothefat sanchothefat
22 mar 2011 19:36:16

Funziona perfettamente per me! Soluzione davvero elegante. Ti devo una birra :)

Michal Mau Michal Mau
26 apr 2011 14:31:51

@somatic Funziona benissimo, ma c'è un modo per far sì che $term->count conti solo i termini per quel tipo di post? Ad esempio, se ho una tassonomia personalizzata sia per foto che per video, quando guardo il tipo di post personalizzato dei video mi mostra il numero totale di post per quel termine da entrambi i tipi di post personalizzati invece che solo il numero totale di post video che usano quel termine.

Greenhoe Greenhoe
11 giu 2015 16:40:45

Puoi migliorare la riga echo "<option value=''>Show All $tax_name</option>"; con $tax_labels = get_taxonomy_labels( $tax_obj ); poi echo "<option value=''>". sprintf( __( 'Mostra %s', 'textdomain'), mb_strtolower( $tax_labels->all_items ) ) ."</option>";

ZalemCitizen ZalemCitizen
29 mar 2024 16:37:15
Mostra i restanti 1 commenti
1
13

Ecco una versione che crea e applica automaticamente filtri da tutte le tassonomie che si applicano a tutti i tipi di post personalizzati che le utilizzano. (Che boccone!) In ogni caso, l'ho anche modificata per funzionare con wp_dropdown_categories() e WordPress 3.1. Il progetto su cui sto lavorando si chiama ToDo, puoi rinominare le funzioni con qualcosa che abbia senso per te, ma questo dovrebbe funzionare praticamente per tutto automaticamente.

function todo_restrict_manage_posts() {
    global $typenow;
    $args=array( 'public' => true, '_builtin' => false ); 
    $post_types = get_post_types($args);
    if ( in_array($typenow, $post_types) ) {
    $filters = get_object_taxonomies($typenow);
        foreach ($filters as $tax_slug) {
            $tax_obj = get_taxonomy($tax_slug);
            wp_dropdown_categories(array(
                'show_option_all' => __('Mostra Tutti '.$tax_obj->label ),
                'taxonomy' => $tax_slug,
                'name' => $tax_obj->name,
                'orderby' => 'term_order',
                'selected' => $_GET[$tax_obj->query_var],
                'hierarchical' => $tax_obj->hierarchical,
                'show_count' => false,
                'hide_empty' => true
            ));
        }
    }
}
function todo_convert_restrict($query) {
    global $pagenow;
    global $typenow;
    if ($pagenow=='edit.php') {
        $filters = get_object_taxonomies($typenow);
        foreach ($filters as $tax_slug) {
            $var = &$query->query_vars[$tax_slug];
            if ( isset($var) ) {
                $term = get_term_by('id',$var,$tax_slug);
                $var = $term->slug;
            }
        }
    }
    return $query;
}
add_action( 'restrict_manage_posts', 'todo_restrict_manage_posts' );
add_filter('parse_query','todo_convert_restrict');

Nota che sto usando un plugin che aggiunge 'term_order' come modo per ordinare i termini, dovrai cambiarlo o rimuovere quell'argomento per tornare al valore predefinito.

23 mar 2011 22:40:00
Commenti

davvero molto sexy. stavo ricevendo notifiche di errore, quindi ho cambiato if ( isset($var)) in if ( isset($var) && $var>0) per evitare di cercare termini associati al valore 0 di View all. ah, e ho dovuto restituire $query nella funzione todo_convert_restrict

helgatheviking helgatheviking
8 gen 2012 00:17:27
7
11

Risposta tardiva

Modifica

Ho scritto Filterama, un plugin che aggiungerà questa funzionalità nel modo più semplice possibile.

Aggiornamento per WordPress 3.5+

Ora che le cose sono molto più semplici, ecco una soluzione molto semplice come plugin o mu-plugin.

Utilizza il minor numero di risorse possibile, si carica solo sugli schermi necessari e aggiunge Colonne + Filtri per ogni tassonomia personalizzata.

add_action( 'plugins_loaded', array( 'WCM_Admin_PT_List_Tax_Filter', 'init' ) );
class WCM_Admin_PT_List_Tax_Filter
{
    private static $instance;

    public $post_type;

    public $taxonomies;

    static function init()
    {
        null === self::$instance AND self::$instance = new self;
        return self::$instance;
    }

    public function __construct()
    {
        add_action( 'load-edit.php', array( $this, 'setup' ) );
    }

    public function setup()
    {
        add_action( current_filter(), array( $this, 'setup_vars' ), 20 );

        add_action( 'restrict_manage_posts', array( $this, 'get_select' ) );

        add_filter( "manage_taxonomies_for_{$this->post_type}_columns", array( $this, 'add_columns' ) );
    }

    public function setup_vars()
    {
        $this->post_type  = get_current_screen()->post_type;
        $this->taxonomies = array_diff(
            get_object_taxonomies( $this->post_type ),
            get_taxonomies( array( 'show_admin_column' => 'false' ) )
        );
    }

    public function add_columns( $taxonomies )
    {
        return array_merge( $taxonomies, $this->taxonomies );
    }


    public function get_select()
    {
        $walker = new WCMF_walker;
        foreach ( $this->taxonomies as $tax )
        {
            wp_dropdown_categories( array(
                'taxonomy'        => $tax,
                'hide_if_empty'   => true,
                'show_option_all' => sprintf(
                    get_taxonomy( $tax )->labels->all_items
                ),
                'hide_empty'      => true,
                'hierarchical'    => is_taxonomy_hierarchical( $tax ),
                'show_count'      => true,
                'orderby'         => 'name',
                'selected'        => '0' !== get_query_var( $tax )
                    ? get_query_var( $tax )
                    : false,
                'name'            => $tax,
                'id'              => $tax,
                'walker'          => $walker,
            ) );
        }

    }

}

E poi hai solo bisogno di una classe Walker personalizzata.

class WCMF_walker extends Walker_CategoryDropdown
{
    public $tree_type = 'category';
    public $db_fields = array(
        'parent' => 'parent',
        'id'     => 'term_id',
    );
    public $tax_name;

    public function start_el( &$output, $term, $depth, $args, $id = 0 )
    {
        $pad = str_repeat( '&nbsp;', $depth * 3 );
        $cat_name = apply_filters( 'list_cats', $term->name, $term );
        $output .= sprintf(
            '<option class="level-%s" value="%s" %s>%s%s</option>',
            $depth,
            $term->slug,
            selected(
                $args['selected'],
                $term->slug,
                false
            ),
            $pad.$cat_name,
            $args['show_count']
                ? "&nbsp;&nbsp;({$term->count})"
                : ''
        );
    }
}
19 gen 2013 21:57:01
Commenti

Ho provato a fare questa modifica, ma il metodo get_select() sembra essere mancante.

Dave Romsey Dave Romsey
15 mar 2013 17:40:39

@goto10 Avevi ragione. Ho aggiornato. A proposito: è più semplice scaricare direttamente il plugin collegato. Sarà disponibile nel repository dei plugin tra una o due settimane. (Già confermato).

kaiser kaiser
16 mar 2013 13:09:12

Ho dovuto usare $this->setup_vars(); all'inizio di public function setup() per far funzionare "manage_taxonomies_for_{$this->post_type}_columns"

Christian Christian
2 lug 2013 14:44:22

Ma potrebbe essere perché lo uso nel file function.php del Tema con add_action( 'init', array( 'WCM_Admin_PT_List_Tax_Filter', 'init' ) );

Christian Christian
2 lug 2013 14:52:45

@Christian Questo non è materiale da tema. Appartiene a un plugin e così com'è scritto il codice sopra, viene caricato molto prima che i Temi vengano caricati.

kaiser kaiser
2 lug 2013 15:49:28

Il plugin non ha funzionato per me in WP 4.8

BadHorsie BadHorsie
18 ago 2017 19:38:26

@BadHorsie Per favore prova a usare il dev–Branch. Ho iniziato il refactoring, ma non ho trovato il tempo per completarlo.

kaiser kaiser
18 ago 2017 21:08:51
Mostra i restanti 2 commenti
0

Volevo solo fare una breve nota. Nelle versioni più recenti di WP, gli elenchi di articoli nell'area di amministrazione sono gestiti dalla classe WP_Posts_List_Table. Il codice apply_filters ora è il seguente:

if ( 'page' == $post_type )
        $posts_columns = apply_filters( 'manage_pages_columns', $posts_columns );
    else
        $posts_columns = apply_filters( 'manage_posts_columns', $posts_columns, $post_type );
    $posts_columns = apply_filters( "manage_{$post_type}_posts_columns", $posts_columns );

Quindi per aggiungere nuove colonne un hook add_filter dovrebbe essere così:

add_filter( 'manage_posts_columns', 'my_add_columns', 10, 2);

Ecco un esempio:

function my_add_columns($posts_columns, $post_type)
{
  if ('myposttype' == $post_type) {
    $posts_columns = array(
      "cb"            => "<input type=\"checkbox\" />",
      "title"         => "Titolo",
      "anothercolumn" => "Bacon",
      "date"          => __( 'Data' )
    );
    return $posts_columns;
  }
} 

Ora, per le righe degli articoli. Questo è il codice che gestisce i dati delle colonne negli elenchi:

default:
            ?>
            <td <?php echo $attributes ?>><?php
                if ( is_post_type_hierarchical( $post->post_type ) )
                    do_action( 'manage_pages_custom_column', $column_name, $post->ID );
                else
                    do_action( 'manage_posts_custom_column', $column_name, $post->ID );
                do_action( "manage_{$post->post_type}_posts_custom_column", $column_name, $post->ID );
            ?></td>
            <?php

Per recuperare i dati dei nostri articoli, dobbiamo aggiungere un action hook in questo modo:

add_action( "manage_(here_goes_your_post_type)_posts_custom_column", "my_posttype_add_column", 10, 2);

Esempio (questo esempio usa tassonomie, ma potresti interrogare qualsiasi altra cosa):

function my_posttype_add_column($column_name, $post_id)
{
  switch ($column_name) {
    case 'anothercolumn':
      $flavours = get_the_terms($post_id, 'flavour');
      if (is_array($flavours)) {
        foreach($flavours as $key => $flavour) {
          $edit_link = get_term_link($flavour, 'flavour');
          $flavours[$key] = '<a href="'.$edit_link.'">' . $flavour->name . '</a>';
        }
        echo implode(' | ',$flavours);
      }
      break;

    default:
      break;
  }
}
29 ago 2011 14:44:11
2

FUNZIONA IN WP 3.2!

custom_post_type: books custom_taxonomy: genre

Modificare solo dove indica: // change HERE

function restrict_books_by_genre() {
    global $typenow;
    $post_type = 'books'; // change HERE
    $taxonomy = 'genre'; // change HERE
    if ($typenow == $post_type) {
        $selected = isset($_GET[$taxonomy]) ? $_GET[$taxonomy] : '';
        $info_taxonomy = get_taxonomy($taxonomy);
        wp_dropdown_categories(array(
            'show_option_all' => __("Mostra Tutti {$info_taxonomy->label}"),
            'taxonomy' => $taxonomy,
            'name' => $taxonomy,
            'orderby' => 'name',
            'selected' => $selected,
            'show_count' => true,
            'hide_empty' => true,
        ));
    };
}

add_action('restrict_manage_posts', 'restrict_books_by_genre');


function convert_id_to_term_in_query($query) {
    global $pagenow;
    $post_type = 'books'; // change HERE
    $taxonomy = 'genre'; // change HERE
    $q_vars = &$query->query_vars;
    if ($pagenow == 'edit.php' && isset($q_vars['post_type']) && $q_vars['post_type'] == $post_type && isset($q_vars[$taxonomy]) && is_numeric($q_vars[$taxonomy]) && $q_vars[$taxonomy] != 0) {
        $term = get_term_by('id', $q_vars[$taxonomy], $taxonomy);
        $q_vars[$taxonomy] = $term->slug;
    }
}

add_filter('parse_query', 'convert_id_to_term_in_query');
16 ott 2011 06:54:53
Commenti

Questa è una bella e semplice soluzione per WP 3.2+.

petermolnar petermolnar
30 lug 2015 13:27:00

funziona ma __("Show All {$info_taxonomy->label}") è un modo sbagliato di usare le stringhe traducibili.

Mark Kaplun Mark Kaplun
23 ago 2017 08:24:24
1

Ho dovuto lavorare su una funzionalità simile non molto tempo fa, poiché non ero soddisfatto delle risposte esistenti, ecco la mia alternativa. Anno 2021.

Volevo qualcosa di semplice e immediato da implementare. Ottenere rapidamente ed efficientemente tutte le tassonomie personalizzate da ogni tipo di post personalizzato e aggiungerle come opzioni di filtro.

C'erano alcuni prerequisiti:

  • Volevo evitare di utilizzare variabili globali.
  • Il codice doveva essere portatile, senza variabili hardcoded, per essere riutilizzabile.
  • Avere una sorta di gerarchia visibile, perfetta per tassonomie con molti termini correlati.
  • Doveva rispettare la scelta di visibilità della tassonomia. (es: parametro show_admin_column della funzione register_taxonomy).
  • Visualizzare il conteggio dei post.
  • L'aspetto generale doveva corrispondere a quello di WordPress.

L'ho trasformato in un plugin per un'integrazione più semplice, puoi ottenere l'ultima versione su https://wordpress.org/plugins/cpt-admin-taxonomy-filtering/.

Filtro con gerarchia di termini e conteggio post Filtri per più tipi di post personalizzati
Filtro con gerarchia di termini e conteggio post Filtri per più tipi di post personalizzati

Se vuoi semplicemente aggiungerlo al tuo function.php, copia e incolla il seguente script.

Richiede almeno WordPress 4.8.0 & PHP: 4.0.

<?php

add_action( 'restrict_manage_posts', 'cpt_admin_taxonomy_filtering' );

if ( ! function_exists( 'cpt_admin_taxonomy_filtering' ) ) {

    function cpt_admin_taxonomy_filtering() {

        /**
         * Ottiene l'oggetto screen corrente.
         * 
         * @link https://developer.wordpress.org/reference/functions/get_current_screen/
         */
        $screen = get_current_screen();

        // Escludi i tipi di post predefiniti di WordPress
        $restricted_post_types = array(
            'post',
            'page',
            'attachment',
            'revision',
            'nav_menu_item',
        );

        if ( 'edit' === $screen->base && ! in_array( $screen->post_type, $restricted_post_types ) {

            /**
             * Restituisce i nomi o gli oggetti delle tassonomie registrate per l'oggetto o tipo di oggetto richiesto, come un oggetto post o nome del tipo di post.
             * 
             * @link https://developer.wordpress.org/reference/functions/get_object_taxonomies/
             */
            $taxonomies = get_object_taxonomies( $screen->post_type, 'objects' );

            // Scorri ogni tassonomia
            foreach ( $taxonomies as $taxonomy ) {

                if ( $taxonomy->show_admin_column ) {

                    /**
                     * Visualizza o recupera il menu a discesa HTML delle categorie.
                     * 
                     * @link https://developer.wordpress.org/reference/functions/wp_dropdown_categories/
                     */
                    wp_dropdown_categories(
                        array(
                            'show_option_all' => $taxonomy->labels->all_items,
                            'pad_counts' => true,
                            'show_count' => true,
                            'hierarchical' => true,
                            'name' => $taxonomy->query_var,
                            'id' => 'filter-by-' . $taxonomy->query_var,
                            'class' => '',
                            'value_field' => 'slug',
                            'taxonomy' => $taxonomy->query_var,
                            'hide_if_empty' => true,
                        )
                    );

                };

            };

        };

    };

};
1 mag 2021 16:39:29
Commenti

Funziona davvero bene, grazie!

Gavin Gavin
17 lug 2021 05:25:59
0

Non è molto conosciuto credo, ma a partire da WordPress 3.5, puoi passare 'show_admin_column' => true a register_taxonomy. Questo fa due cose:

  1. Aggiunge la colonna della tassonomia alla vista a elenco del tipo di post nell'amministrazione
  2. Cliccando sul nome del termine nella colonna della tassonomia, filtra effettivamente l'elenco per quel termine.

Quindi, non esattamente lo stesso che avere un select, ma quasi la stessa funzionalità, con solo una riga di codice.

https://make.wordpress.org/core/2012/12/11/wordpress-3-5-admin-columns-for-custom-taxonomies/

Inoltre, come puoi leggere, c'è un nuovo filtro appositamente per aggiungere manualmente la colonna della tassonomia (se ne hai davvero bisogno).

15 set 2017 15:00:54
2

Grazie a tutti per le risposte. So che è una domanda vecchia, ma vorrei aggiungere la soluzione più semplice che può essere utilizzata oggi. Richiederà solo 2 passaggi e utilizzerà più funzionalità del core disponibili. Spero che questo possa aiutare qualcuno.

Passo 1: aggiungi 'show_admin_column' => true alla tua funzione register_taxonomy.

Questo aggiungerà una colonna alla vista elenco contenente i link per filtrare la lista per quel termine. Può essere applicato sia per tassonomie gerarchiche che non gerarchiche.

Esempio:

register_taxonomy( 'custom_cat', array( 'custom_post_type' ), array(
    'hierarchical'      => true,
    'labels'            => array(
        'name'              => __( 'Categorie', 'iside' ),
        'singular_name'     => __( 'Categoria', 'iside' ),
        'search_items'      => __( 'Cerca Categorie', 'iside' ),
        'all_items'         => __( 'Tutte le Categorie', 'iside' ),
        'parent_item'       => __( 'Categoria Genitore', 'iside' ),
        'parent_item_colon' => __( 'Categoria Genitore:', 'iside' ),
        'edit_item'         => __( 'Modifica Categoria', 'iside' ),
        'update_item'       => __( 'Aggiorna Categoria', 'iside' ),
        'add_new_item'      => __( 'Aggiungi Nuova Categoria', 'iside' ),
        'new_item_name'     => __( 'Nuova Categoria', 'iside' ),
        'menu_name'         => __( 'Categorie', 'iside' ),
    ),
    'public'            => true,
    'publicly_queryable'=> true,
    'show_ui'           => true,
    'show_in_menu'      => true,
    'show_in_nav_menus' => true,
    'show_in_rest'      => true,
    'show_tagcloud'     => false,
    'show_in_quick_edit'=> true,
    'show_admin_column' => true, // <-- la magia applicata qui
    'query_var'         => true,
) );

Passo 2: aggiungi il dropdown della tassonomia tramite il filtro restrict_manage_posts

Questo aggiungerà un menu a tendina alle opzioni di filtro in alto. Utilizzerà la funzione predefinita wp_dropdown_categories per semplificare. Nota che dobbiamo impostare il nome del dropdown al query_var che usiamo per la tassonomia. Inoltre il value_field deve essere impostato sullo slug (di default sarà il term_id).

Esempio:

add_action( 'restrict_manage_posts', 'iside_add_filter_to_admin', 10, 2 );
function iside_add_filter_to_admin( $post_type = 'post', $which = 'top' ) {
    if( $post_type == 'custom_post_type' ) {
        $selected = isset( $_GET['custom_cat'] ) ? esc_attr($_GET['custom_cat']) : 0;
        wp_dropdown_categories(array(
            'show_option_all' =>  __( 'Mostra Tutte le Categorie', 'iside' ),
            'taxonomy'        =>  'custom_cat',
            'name'            =>  'custom_cat', // <-- assicurati che corrisponda al query_var
            'orderby'         =>  'name',
            'selected'        =>  $selected,
            'hierarchical'    =>  true,
            'depth'           =>  3,
            'show_count'      =>  true,
            'hide_empty'      =>  true,
            'value_field'     => 'slug', // <-- usa lo slug invece del term_id
        ));
    }
}

Ecco fatto. Non c'è bisogno di aggiungere altro :-)

18 mar 2022 11:52:55
Commenti

Molto carino e semplice, grazie. Un punto da notare - c'è un errore nella tua sintassi qui (c'è una parentesi in più): $selected = isset( $_GET['custom_cat'] ) ? esc_attr($_GET['custom_cat') ]) : 0; che dovrebbe invece essere così: $selected = isset( $_GET['custom_cat'] ) ? esc_attr($_GET['custom_cat' ]) : 0;

SolaceBeforeDawn SolaceBeforeDawn
27 mag 2023 09:05:51

Grazie @SolaceBeforeDawn. Ho modificato la mia risposta

leendertvb leendertvb
27 mag 2023 23:30:21
0

Ecco un modo per farlo utilizzando l'azione restrict_manage_posts. Sembra funzionare bene per me e aggiunge la possibilità di filtrare per tassonomia per tutti i tipi di post e le relative tassonomie.

// registra ciascuno dei menu a discesa per il filtro delle tassonomie
function sunrise_fbt_add_taxonomy_filters() {
    global $typenow;            // il tipo di post corrente
    $taxonomies = get_taxonomies('','objects');
    foreach($taxonomies as $taxName => $tax) {
    if(in_array($typenow,$tax->object_type) && $taxName != 'category' && $taxName != 'tags') {
            $terms = get_terms($taxName);
            if(count($terms) > 0) {
              //Controlla se è gerarchica - in tal caso costruisce un menu a discesa gerarchico
              if($tax->hierarchical) {
                $args = array(
                      'show_option_all'    => 'Tutti '.$tax->labels->name,
                      'show_option_none'   => 'Seleziona '.$tax->labels->name,
                      'show_count'         => 1,
                      'hide_empty'         => 0, 
                      'echo'               => 1,
                      'hierarchical'       => 1,
                      'depth'              => 3, 
                      'name'               => $tax->rewrite['slug'],
                      'id'                 => $tax->rewrite['slug'],                      
                      'class'              => 'postform',
                      'depth'              => 0,
                      'tab_index'          => 0,
                      'taxonomy'           => $taxName,
                      'hide_if_empty'      => false);
            $args['walker'] = new Walker_FilterByTaxonomy;
                wp_dropdown_categories($args);
              } else {
                    echo "<select name='".$tax->rewrite['slug']."' id='".$tax->rewrite['slug']."' class='postform'>";
                    echo "<option value=''>Mostra Tutti ".$tax->labels->name."</option>";
                    foreach ($terms as $term) { 
              echo '<option value="' . $term->slug . '"', $_GET[$taxName] == $term->slug ? ' selected="selected"' : '','>' . $term->name .' (' . $term->count .')</option>'; 
            }
                    echo "</select>";
                }
            }
    }
    }
}
add_action( 'restrict_manage_posts', 'sunrise_fbt_add_taxonomy_filters', 100 );

/**
 * Crea un elenco HTML a discesa di Categorie.
 *
 * @package WordPress
 * @since 2.1.0
 * @uses Walker
 */
class Walker_FilterByTaxonomy extends Walker {
    var $tree_type = 'category';
    var $db_fields = array ('parent' => 'parent', 'id' => 'term_id');
    function start_el(&$output, $category, $depth, $args) {
      $args['selected'] = get_query_var( $args['taxonomy'] );
        $pad = str_repeat('&nbsp;', $depth * 3);

        $cat_name = apply_filters('list_cats', $category->name, $category);
        $output .= "\t<option class=\"level-$depth\" value=\"".$category->slug."\"";
        if ( $category->slug == $args['selected'] )
            $output .= ' selected="selected"';
        $output .= '>';
        $output .= $pad.$cat_name;
        if ( $args['show_count'] )
            $output .= '&nbsp;&nbsp;('. $category->count .')';
        if ( $args['show_last_update'] ) {
            $format = 'Y-m-d';
            $output .= '&nbsp;&nbsp;' . gmdate($format, $category->last_update_timestamp);
        }
        $output .= "</option>\n";
        }
} 

Una nota - ho provato a limitare la profondità perché alcune delle mie tassonomie gerarchiche sono piuttosto grandi ma non ha funzionato - potrebbe essere un bug nella funzione wp_dropdown_categories?

17 feb 2012 21:53:24
0

Aggiornamento della risposta di @Drew Gourley per WP 3.3.1 (e integrazione del codice da http://wordpress.org/support/topic/wp_dropdown_categories-generating-url-id-number-instead-of-slug?replies=6#post-2529115):

add_action('restrict_manage_posts', 'xyz_restrict_manage_posts');
function xyz_restrict_manage_posts() {
    global $typenow;

    $args = array('public'=>true, '_builtin'=>false); 
    $post_types = get_post_types($args);

    if(in_array($typenow, $post_types)) {
        $filters = get_object_taxonomies($typenow);

        foreach ($filters as $tax_slug) {
            $tax_obj = get_taxonomy($tax_slug);
            $term = get_term_by('slug', $_GET[$tax_obj->query_var], $tax_slug);

            wp_dropdown_categories(array(
                'show_option_all' => __('Mostra Tutti '.$tax_obj->label ),
                'taxonomy' => $tax_slug,
                'name' => $tax_obj->name,
                'orderby' => 'term_order',
                'selected' => $term->term_id,
                'hierarchical' => $tax_obj->hierarchical,
                'show_count' => false,
                // 'hide_empty' => true,
                'hide_empty' => false,
                'walker' => new DropdownSlugWalker()
            ));
        }
    }
}


//Classe per il filtro a discesa. Usata con wp_dropdown_categories() per far sì che il menu a discesa risultante utilizzi gli slug dei termini invece degli ID.
class DropdownSlugWalker extends Walker_CategoryDropdown {

    function start_el(&$output, $category, $depth, $args) {
        $pad = str_repeat('&nbsp;', $depth * 3);

        $cat_name = apply_filters('list_cats', $category->name, $category);
        $output .= "\t<option class=\"level-$depth\" value=\"".$category->slug."\"";

        if($category->term_id == $args['selected'])
            $output .= ' selected="selected"';

        $output .= '>';
        $output .= $pad.$cat_name;
        $output .= "</option>\n";
    }
}
25 gen 2013 22:47:17
0

Versione gerarchica della risposta di @somatic, come richiesto da @kevin:

<?php
add_action( 'restrict_manage_posts', 'my_restrict_manage_posts' );
function my_restrict_manage_posts() {

    // mostra questi filtri tassonomici solo negli elenchi dei post type desiderati
    global $typenow;
    if ($typenow == 'photos' || $typenow == 'videos') {

        // crea un array di slug di tassonomie da filtrare - se vuoi recuperare tutte le tassonomie, potresti usare get_taxonomies() per costruire la lista
        $filters = array('plants', 'animals', 'insects');

        foreach ($filters as $tax_slug) {
            // recupera l'oggetto tassonomia
            $tax_obj = get_taxonomy($tax_slug);
            $tax_name = $tax_obj->labels->name;

            // output html per il dropdown di filtraggio tassonomico
            echo "<select name='$tax_slug' id='$tax_slug' class='postform'>";
            echo "<option value=''>Mostra Tutti $tax_name</option>";
            generate_taxonomy_options($tax_slug,0,0);
            echo "</select>";
        }
    }
}

function generate_taxonomy_options($tax_slug, $parent = '', $level = 0) {
    $args = array('show_empty' => 1);
    if(!is_null($parent)) {
        $args = array('parent' => $parent);
    } 
    $terms = get_terms($tax_slug,$args);
    $tab='';
    for($i=0;$i<$level;$i++){
        $tab.='--';
    }
    foreach ($terms as $term) {
        // output per ogni opzione select, verifica l'ultimo $_GET per mostrare l'opzione corrente selezionata
        echo '<option value='. $term->slug, $_GET[$tax_slug] == $term->slug ? ' selected="selected"' : '','>' .$tab. $term->name .' (' . $term->count .')</option>';
        generate_taxonomy_options($tax_slug, $term->term_id, $level+1);
    }

}
?>

Ho sostanzialmente rimosso il codice che creava le opzioni e l'ho messo in una funzione separata. La funzione 'generate_taxonomy_options', oltre a prendere il tax_slug, accetta anche i parametri parent e level. La funzione assume che stia creando opzioni per il parent 0, che selezionerà tutti i termini di livello root. Nel loop la funzione richiamerà se stessa ricorsivamente, usando il termine corrente come parent e incrementando il livello di uno. Aggiunge automaticamente trattini sul lato più si scende nell'albero ed ecco fatto!

7 gen 2011 09:12:50
1

Aggiungi semplicemente questo al tuo functions.php o al codice del plugin (e sostituisci YOURCUSTOMTYPE e YOURCUSTOMTAXONOMY). (Ho preso il codice da generatewp)

add_action( 'restrict_manage_posts', 'filter_backend_by_taxonomies' , 99, 2);

function filter_backend_by_taxonomies( $post_type, $which ) {
    // Applica questo a un CPT specifico
    if ( 'YOURCUSTOMTYPE' !== $post_type )
        return;
    // Una lista di slug di tassonomie personalizzate da filtrare
    $taxonomies = array( 'YOURCUSTOMTAXONOMY' );
    foreach ( $taxonomies as $taxonomy_slug ) {
        // Recupera i dati della tassonomia
        $taxonomy_obj = get_taxonomy( $taxonomy_slug );
        $taxonomy_name = $taxonomy_obj->labels->name;
        // Recupera i termini della tassonomia
        $terms = get_terms( $taxonomy_slug );
        // Mostra l'HTML del filtro
        echo "<select name='{$taxonomy_slug}' id='{$taxonomy_slug}' class='postform'>";
        echo '<option value="">' . sprintf( esc_html__( 'Categoria', 'text_domain' ), $taxonomy_name ) . '</option>';
        foreach ( $terms as $term ) {
            printf(
                '<option value="%1$s" %2$s>%3$s (%4$s)</option>',
                $term->slug,
                ( ( isset( $_GET[$taxonomy_slug] ) && ( $_GET[$taxonomy_slug] == $term->slug ) ) ? ' selected="selected"' : '' ),
                $term->name,
                $term->count
            );
        }
        echo '</select>';
    }
}
29 giu 2020 14:28:23
Commenti

Eccellente! La migliore risposta!

Carl Brubaker Carl Brubaker
21 apr 2021 23:42:23
0

Il tutorial di Mike su questo argomento è fantastico! Probabilmente non mi sarei preoccupato di aggiungere questa funzionalità al mio plugin Media Categories se avessi dovuto capirlo da solo.

Detto questo, penso che utilizzare parse_query e poi interrogare il termine non sia necessario. È più pulito creare la propria classe walker personalizzata. Forse non era possibile quando ha scritto il suo post - risale a 3 anni fa al momento in cui scrivo questo.

Dai un'occhiata a questo fantastico snippet su GitHub. Funziona perfettamente, cambia gli ID nei valori del dropdown in slug, quindi funziona in modo nativo senza modificare la query.

https://gist.github.com/stephenh1988/2902509

27 mar 2014 22:04:55
1

Ho provato entrambi i codici, quello di Mike e quello di somatic, e mi chiedevo come ottenere una cosa da ciascuna tecnica:

Con il codice di Mike, mostra il menu a discesa con l'opzione gerarchica, che aiuta molto. Ma per visualizzare due menu a discesa ho dovuto duplicare l'istruzione if ($typenow=='produtos') {...} nella funzione restrict_listings_by_business() e anche il if ($pagenow=='edit.php' && ... } nella funzione convert_business_id_to_taxonomy_term_in_query($query) che ora genera molto codice.

Con il codice di somatic mi basta specificare le tassonomie che vorrei vedere come menu a discesa e voilà, funziona; $filters = array('taxo1', 'taxo2');

Domanda: posso ottenere l'approccio di somatic e avere anche l'opzione gerarchica?

Grazie comunque per questo tutorial, è stato di grande aiuto!

6 gen 2011 21:00:53
Commenti

Ecco la mia risposta per una soluzione gerarchica

Manny Fleurmond Manny Fleurmond
8 gen 2011 08:02:39
0

Questo è un potente snippet che permette di filtrare i tuoi post o custom post type per un termine specifico di una tassonomia nell'area di amministrazione di WordPress.

/* Filtra CPT tramite Tassonomia Personalizzata */
function rave_core_backend_by_portfolio_taxonomies( $post_type, $which ) {
    // Applica questo filtro solo a un specifico CPT
    if ( 'portfolio' !== $post_type )
        return;

    // Una lista di slug di tassonomie personalizzate da filtrare
    $taxonomies = array( 'portfolio_cat' );

    foreach ( $taxonomies as $taxonomy_slug ) {

        // Recupera i dati della tassonomia
        $taxonomy_obj = get_taxonomy( $taxonomy_slug );
        $taxonomy_name = $taxonomy_obj->labels->name;

        // Recupera i termini della tassonomia
        $terms = get_terms( $taxonomy_slug );

        // Mostra l'HTML del filtro
        echo "<select name='{$taxonomy_slug}' id='{$taxonomy_slug}' class='postform'>";
        echo '<option value="">' . sprintf( esc_html__( 'Tutti i %s', 'rave-core' ), $taxonomy_name ) . '</option>';
        foreach ( $terms as $term ) {
            printf(
                '<option value="%1$s" %2$s>%3$s (%4$s)</option>',
                $term->slug,
                ( ( isset( $_GET[$taxonomy_slug] ) && ( $_GET[$taxonomy_slug] == $term->slug ) ) ? ' selected="selected"' : '' ),
                $term->name,
                $term->count
            );
        }
        echo '</select>';
    }
}

add_action( 'restrict_manage_posts', 'rave_core_backend_by_portfolio_taxonomies' , 99, 2);
13 giu 2021 08:51:24
1

Mi scuso per il fatto che, essendo un nuovo utente, non posso pubblicare commenti ma posso pubblicare una risposta...

A partire da WordPress 3.1 (RC 1) la risposta di Mike (che mi è stata così utile negli ultimi mesi) non funziona più per me; limitare per qualsiasi tassonomia figlia restituisce un risultato vuoto.

Ho provato l'aggiornamento di Somatic e ha funzionato alla grande; ancora meglio, funziona con query multiple di tassonomie che sono state integrate in questa versione.

27 dic 2010 22:37:04
Commenti

Per qualche motivo, nemmeno la versione di somatic funziona per la 3.1

Manny Fleurmond Manny Fleurmond
24 feb 2011 08:17:18