Adicionando um filtro de taxonomia à lista de administradores para um tipo de postagem personalizado?

Criei um tipo de postagem personalizado chamado 'listing' e adicionei uma taxonomia personalizada chamada 'businesses' . Gostaria de adicionar uma lista suspensa de Empresas à lista de administradores para os Listados.

Aqui está o aspecto desta funcionalidade na lista de administradores para postagens (eu gostaria do mesmo para meu tipo de postagem personalizado):

Categorias Dropdown em postagens

Aqui está o meu código atual ( E aqui está o mesmo código no Gist. ):

  array( 'name' => __('Listings'), 'singular_name' => __( 'Listing' ), 'add_new' => __( 'Add Listing' ), 'add_new_item' => __( 'Add New Listing' ), 'edit' => __( 'Edit' ), 'edit_item' => __( 'Edit Listing' ), 'new_item' => __( 'New Listing' ), 'view' => __( 'View Listing' ), 'view_item' => __( 'View Listing' ), 'search_items' => __( 'Search Listings' ), 'not_found' => __( 'No listings found' ), 'not_found_in_trash' => __( 'No listings found in Trash' ), 'parent' => __( 'Parent Listing' ), ), 'singular_label' => __('Listing'), 'public' => true, 'show_ui' => true, // UI in admin panel '_builtin' => false, // It's a custom post type, not built in '_edit_link' => 'post.php?post=%d', 'capability_type' => 'post', 'hierarchical' => false, 'rewrite' => array("slug" => "listings"), // Permalinks 'query_var' => "listings", // This goes to the WP_Query schema 'supports' => array('title','editor') )); add_filter("manage_edit-listing_columns", array(&$this, "edit_columns")); add_action("manage_posts_custom_column", array(&$this, "custom_columns")); // Register custom taxonomy #Businesses register_taxonomy("businesses", array("listing"), array( "hierarchical" => true, "label" => "Listing Categories", "singular_label" => "Listing Categorie", "rewrite" => true, )); # Region register_taxonomy("regions", array("listing"), array( 'labels' => array( 'search_items' => __( 'Search Regions' ), 'popular_items' => __( 'Popular Regions' ), 'all_items' => __( 'All Regions' ), 'parent_item' => null, 'parent_item_colon' => null, 'edit_item' => __( 'Edit Region' ), 'update_item' => __( 'Update Region' ), 'add_new_item' => __( 'Add New Region' ), 'new_item_name' => __( 'New Region Name' ), 'separate_items_with_commas' => __( 'Separate regions with commas' ), 'add_or_remove_items' => __( 'Add or remove regions' ), 'choose_from_most_used' => __( 'Choose from the most used regions' ), ), "hierarchical" => false, "label" => "Listing Regions", "singular_label" => "Listing Region", "rewrite" => true, )); # Member Organizations register_taxonomy("organizations", array("listing"), array( 'labels' => array( 'search_items' => __( 'Search Member Organizations' ), 'popular_items' => __( 'Popular Member Organizations' ), 'all_items' => __( 'All Member Organizations' ), 'parent_item' => null, 'parent_item_colon' => null, 'edit_item' => __( 'Edit Member Organization' ), 'update_item' => __( 'Update Member Organization' ), 'add_new_item' => __( 'Add New Member Organization' ), 'new_item_name' => __( 'New Member Organization Name' ), 'separate_items_with_commas' => __( 'Separate member organizations with commas' ), 'add_or_remove_items' => __( 'Add or remove member organizations' ), 'choose_from_most_used' => __( 'Choose from the most used member organizations' ), ), "hierarchical" => false, "label" => "Member Organizations", "singular_label" => "Member Organization", "rewrite" => true, )); # Retail Products register_taxonomy("retails", array("listing"), array( 'labels' => array( 'search_items' => __( 'Search Retail Products' ), 'popular_items' => __( 'Popular Retail Products' ), 'all_items' => __( 'All Retail Products' ), 'parent_item' => null, 'parent_item_colon' => null, 'edit_item' => __( 'Edit Retail Product' ), 'update_item' => __( 'Update Retail Product' ), 'add_new_item' => __( 'Add New Retail Product' ), 'new_item_name' => __( 'New Retail Product Name' ), 'separate_items_with_commas' => __( 'Separate retail products with commas' ), 'add_or_remove_items' => __( 'Add or remove retail products' ), 'choose_from_most_used' => __( 'Choose from the most used retail products' ), ), "hierarchical" => false, "label" => "Retail Products", "singular_label" => "Retail Product", "rewrite" => true, )); # Farming Practices register_taxonomy("practices", array("listing"), array( 'labels' => array( 'search_items' => __( 'Search Farming Practices' ), 'popular_items' => __( 'Popular Farming Practices' ), 'all_items' => __( 'All Farming Practices' ), 'parent_item' => null, 'parent_item_colon' => null, 'edit_item' => __( 'Edit Farming Practice' ), 'update_item' => __( 'Update Farming Practice' ), 'add_new_item' => __( 'Add New Farming Practice' ), 'new_item_name' => __( 'New Farming Practice Name' ), 'separate_items_with_commas' => __( 'Separate farming practices with commas' ), 'add_or_remove_items' => __( 'Add or remove farming practices' ), 'choose_from_most_used' => __( 'Choose from the most used farming practices' ), ), "hierarchical" => false, "label" => "Farming Practices", "singular_label" => "Farming Practice", "rewrite" => true, )); # Products register_taxonomy("products", array("listing"), array( 'labels' => array( 'search_items' => __( 'Search Products' ), 'popular_items' => __( 'Popular Products' ), 'all_items' => __( 'All Products' ), 'parent_item' => null, 'parent_item_colon' => null, 'edit_item' => __( 'Edit Product' ), 'update_item' => __( 'Update Product' ), 'add_new_item' => __( 'Add New Product' ), 'new_item_name' => __( 'New Product Name' ), 'separate_items_with_commas' => __( 'Separate products with commas' ), 'add_or_remove_items' => __( 'Add or remove products' ), 'choose_from_most_used' => __( 'Choose from the most used products' ), ), "hierarchical" => false, "label" => "Products", "singular_label" => "Product", "rewrite" => true, )); // Admin interface init add_action("admin_init", array(&$this, "admin_init")); add_action("template_redirect", array(&$this, 'template_redirect')); // Insert post hook add_action("wp_insert_post", array(&$this, "wp_insert_post"), 10, 2); } function edit_columns($columns) { $columns = array( "cb" => "", "title" => "Business Name", "description" => "Description", "list-personal" => "Personal Information", "list-location" => "Location", "list-categorie" => "Categorie", ); return $columns; } function custom_columns($column) { global $post; switch ($column) { case "description": the_excerpt(); break; case "list-personal": $custom = get_post_custom(); if(isset($custom["list-firstname"][0])) echo $custom["list-firstname"][0]."
"; if(isset($custom["list-lastname"][0])) echo $custom["list-lastname"][0]."
"; if(isset($custom["list-email"][0])) echo $custom["list-email"][0]."
"; if(isset($custom["list-website"][0])) echo $custom["list-website"][0]."
"; if(isset($custom["list-phone"][0])) echo $custom["list-phone"][0]."
"; if(isset($custom["list-mobile"][0])) echo $custom["list-mobile"][0]."
"; if(isset($custom["list-fax"][0])) echo $custom["list-fax"][0]; break; case "list-location": $custom = get_post_custom(); if(isset($custom["list-address1"][0])) echo $custom["list-address1"][0]."
"; if(isset($custom["list-address2"][0])) echo $custom["list-address2"][0]."
"; if(isset($custom["list-city"][0])) echo $custom["list-city"][0]."
"; if(isset($custom["list-province"][0])) echo $custom["list-province"][0]."
"; if(isset($custom["list-postcode"][0])) echo $custom["list-postcode"][0]."
"; if(isset($custom["list-country"][0])) echo $custom["list-country"][0]."
"; if(isset($custom["list-profile"][0])) echo $custom["list-profile"][0]."
"; if(isset($custom["list-distributionrange"][0])) echo $custom["list-distributionrange"][0]."
"; if(isset($custom["list-distributionarea"][0])) echo $custom["list-distributionarea"][0]; break; case "list-categorie": $speakers = get_the_terms(0, "businesses"); $speakers_html = array(); if(is_array($speakers)) { foreach ($speakers as $speaker) array_push($speakers_html, 'slug, 'businesses') . '">' . $speaker->name . ''); echo implode($speakers_html, ", "); } break; } } // Template selection function template_redirect() { global $wp; if (isset($wp->query_vars["post_type"]) && ($wp->query_vars["post_type"] == "listing")) { include(STYLESHEETPATH . "/listing.php"); die(); } } // When a post is inserted or updated function wp_insert_post($post_id, $post = null) { if ($post->post_type == "listing") { // Loop through the POST data foreach ($this->meta_fields as $key) { $value = @$_POST[$key]; if (empty($value)) { delete_post_meta($post_id, $key); continue; } // If value is a string it should be unique if (!is_array($value)) { // Update meta if (!update_post_meta($post_id, $key, $value)) { // Or add the meta data add_post_meta($post_id, $key, $value); } } else { // If passed along is an array, we should remove all previous data delete_post_meta($post_id, $key); // Loop through the array adding new values to the post meta as different entries with the same name foreach ($value as $entry) add_post_meta($post_id, $key, $entry); } } } } function admin_init() { // Custom meta boxes for the edit listing screen add_meta_box("list-pers-meta", "Personal Information", array(&$this, "meta_personal"), "listing", "normal", "low"); add_meta_box("list-meta", "Location", array(&$this, "meta_location"), "listing", "normal", "low"); } function meta_personal() { global $post; $custom = get_post_custom($post->ID); if(isset($custom["list-firstname"][0])) $first_name = $custom["list-firstname"][0];else $first_name = ''; if(isset($custom["list-lastname"][0])) $last_name = $custom["list-lastname"][0];else $last_name = ''; if(isset($custom["list-website"][0])) $website = $custom["list-website"][0];else $website = ''; if(isset($custom["list-phone"][0])) $phone = $custom["list-phone"][0];else $phone = ''; if(isset($custom["list-mobile"][0])) $mobile = $custom["list-mobile"][0];else $mobile = ''; if(isset($custom["list-fax"][0])) $fax = $custom["list-fax"][0];else $fax = ''; if(isset($custom["list-email"][0])) $email = $custom["list-email"][0];else $email = ''; ?>
<input name="list-firstname" value="" />
<input name="list-lastname" value="" />
<input name="list-email" value="" size="40"/>
<input name="list-website" value="" size="40"/>
<input name="list-phone" value="" />
<input name="list-mobile" value="" />
<input name="list-fax" value="" />
ID); if(isset($custom["list-address1"])) $address1 = $custom["list-address1"][0];else $address1 = ''; if(isset($custom["list-address2"])) $address2 = $custom["list-address2"][0];else $address2 = ''; if(isset($custom["list-country"])) $country = $custom["list-country"][0];else $country = ''; if(isset($custom["list-province"])) $province = $custom["list-province"][0];else $province = ''; if(isset($custom["list-city"])) $city = $custom["list-city"][0];else $city = ''; if(isset($custom["list-postcode"])) $post_code = $custom["list-postcode"][0];else $post_code = ''; if(isset($custom["list-profile"])) $profile = $custom["list-profile"][0];else $profile = ''; if(isset($custom["list-distributionrange"])) $distribution_range = $custom["list-distributionrange"][0];else $distribution_range = ''; if(isset($custom["list-distributionarea"])) $distribution_area = $custom["list-distributionarea"][0];else $ddistribution_area = ''; ?>
<input name="list-address1" value="" size="60" />
<input name="list-address2" value="" size="60" />
<input name="list-city" value="" />
<input name="list-postcode" value="" />
<input name="list-profile" value="" size="60" />
<input name="list-distributionrange" value="" size="60" />
<input name="list-distributionarea" value="" size="60" />
loadStyleScripts(); }

Como posso adicionar uma lista suspensa de Empresas na lista de administradores das Listagens?

Solutions Collecting From Web of "Adicionando um filtro de taxonomia à lista de administradores para um tipo de postagem personalizado?"

UPDATE: incluí uma nova resposta completa, mas mesmo assim deixei minha resposta original na parte inferior à qual os primeiros comentários referem.

Olá @tarasm :

Embora eu tenha dito que não deve ser difícil, está um pouco envolvido. Mas antes de cavar no código …

As Imagens:

… vamos verificar algumas capturas de canvas para o produto acabado:

Listagem lista página sem Filtragem:

Página lista lista com sem filtragem

Página da Lista de Listagens Com Filtragem:

Página lista lista com filtragem

O código

Então, aqui vamos … ( Nota: Eu usei uma forma singular para o nome da taxonomia do business , espero que corresponda à sua. De muita experiência com WordPress e desenvolvimento de database no passado, eu acredito que é melhor fazê-lo isso caminho.)

Etapa # 1: O gancho de ação restrict_manage_posts .

A primeira coisa que você precisa fazer é ligar a ação restrict_manage_posts que não tem parâmetros e é chamada de /wp-admin/edit.php (na /wp-admin/edit.php que a chamada está na linha 378.) Isso permitirá que você gere a lista suspensa selecione no local apropriado acima da lista de postagens.

 < ?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' => __("Show All {$business_taxonomy->label}"), 'taxonomy' => $taxonomy, 'name' => 'business', 'orderby' => 'name', 'selected' => $wp_query->query['term'], 'hierarchical' => true, 'depth' => 3, 'show_count' => true, // Show # listings in parens 'hide_empty' => true, // Don't show businesses w/o listings )); } } 

Começamos por verificar a variável $typenow para garantir que estamos de fato em um post_type de listing de listing . Se você não, você receberá esta lista suspensa para todos os tipos de postagem que, em alguns casos, é o que você quer, mas não neste caso.

Em seguida, carregamos informações sobre a taxonomia comercial usando get_taxonomy() . Precisamos recuperar o label para a taxonomia (ou seja, ” Negócios “, podemos ter codificado demais, mas isso não é muito bom se você precisa se internacionalizar mais tarde). Então chamamos wp_dropdown_categories() com todos os argumentos apropriados no $args array para gerar o menu suspenso

 < ?php return wp_dropdown_categories(array( 'show_option_all' => __("Show All {$business_taxonomy->label}"), 'taxonomy' => $taxonomy, 'name' => 'business', 'orderby' => 'name', 'selected' => $wp_query->query['term'], 'hierarchical' => true, 'depth' => 3, 'show_count' => true, // Show # listings in parens 'hide_empty' => true, // Don't show businesses w/o listings )); 

Mas quais são os argumentos apropriados? Vejamos cada um individualmente:

  • show_optional_allshow_optional_all direto, é o que é exibido no menu suspenso no início e quando não houve filtragem aplicada. Em nosso caso, vai ser “Show All Businesses “, mas nós poderíamos chamá-lo de “Listagens para Todos os Negócios” ou o que você quiser.

  • taxonomy – Este argumento diz à function qual a taxonomia para extrair os termos, mesmo que a function tenha categories em seu nome. Na v2.8 e anterior, o WordPress não tinha taxonomias personalizadas, mas quando foram adicionadas, a equipe decidiu que seria mais fácil adicionar um argumento de taxonomia a essa function do que criar outra function com outro nome.

  • name – Este argumento permite que você especifique o valor que o WordPress usa para o atributo de name do elemento

  • orderby – Este argumento diz ao WordPress como solicitar os resultados em ordem alfabética. No nosso caso, especificamos para encomendar o name dos termos na taxonomia, ou seja, os nomes das empresas neste caso.

  • selected – Este argumento é necessário para que o menu suspenso possa mostrar o filtro atual no menu suspenso. Deve ser o term_id do termo de taxonomia selecionado. No nosso caso, pode ser o term_id do “Business # 2” . Onde conseguimos esse valor? Da variável global do WordPress $wp_query ; ele tem uma query propriedade que contém uma matriz de todos os parâmetros de URL e seus valores (a menos que algum plug-in wayward o tenha modificado, é claro). Como o WordPress processa as coisas, haverá um term parâmetro de URL passado no URL quando o usuário clicar o botão do filtro se o usuário selecionou um termo válido (ou seja, um dos negócios listados).

  • hierarchical – Ao definir isso como true você diz à function que respeite a natureza hierárquica da taxonomia e apresente-os em uma visualização em tree se os termos (empresas) de fato tiverem filhos. Para uma captura de canvas para ver como isso se parece, veja abaixo.

  • depth – Este argumento colabora com o argumento hierarchical para determinar quantos níveis de profundidade a function deve ser exibida na exibição de filhos.

  • show_count – Se for true esse argumento exibirá uma contagem de posts entre parênteses à esquerda do nome do termo dentro da lista suspensa. Nesse caso, exibiria uma contagem de listagens associadas a empresas. Para uma captura de canvas para ver como isso se parece, veja abaixo.

  • hide_empty – Finalmente, se houver termos na taxonomia que não estão associados a uma publicação (ou seja, empresas que não estão associadas a uma listview), então, definir isso como true irá excluí-las de serem incluídas no menu suspenso.

Taxonomia Drop Down deve hierarquizar e contar

Etapa 2: o filtro de filtragem parse_query .

Em seguida, chamamos nossas atenções para o gancho de filtro parse_query que tem um parâmetro ( $query ) e é chamado de /wp-includes/query.php (na /wp-includes/query.php que a chamada está na linha 1549.) É chamado quando o WordPress terminou inspecionando o URL e definindo todos os valores apropriados no $wp_query atualmente ativo, incluindo coisas como $wp_query->is_home e $wp_query->is_author , etc.

Depois que o gancho de filtragem parse_query é executado, o WordPress chamará get_posts() e carregará uma lista de postagens com base no que está especificado na $wp_query atualmente ativa. Então, parse_query é muitas vezes um ótimo lugar para obter o WordPress para mudar sua mente sobre quais postagens ele vai carregar.

No seu caso de uso, queremos obter o WordPress para filtrar com base nos negócios selecionados; ou seja, para exibir apenas os Listados que foram associados ao negócio selecionado (eu diria “… apenas os Listados que foram ” categorizados “ pelo negócio selecionado”, mas isso não é técnico correto; a category é sua própria taxonomia em Pare com os business exceto que a category está integrada no WordPress e as business são personalizadas. Mas para aqueles que estão familiarizados com categorizar postagens, isso pode ajudá-lo a entender como eles funcionam de forma quase idêntica. Mas eu divago …)

No código. A primeira coisa que fazemos é pegar uma referência ao $wp_query atualmente ativo $wp_query para que seja mais conveniente trabalhar, assim como como é feito dentro da própria function parse_query() WordPress. Ao contrário de $wp_query->query que é usada para espelhar os parâmetros passados ​​na URL, a $wp_query->query_vars é usada para controlar a consulta que o WordPress executa e espera-se que seja modificado. Então, se você precisar modificar um, esse seria o único (pelo menos eu acho que isso é diferente entre os dois, se alguém souber o contrário, por favor me avise para que eu possa atualizar isso!)

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

Em seguida, testar $pagenow para garantir que estamos realmente carregando o WordPress a partir do caminho URL /wp-admin/edit.php . Fazemos isso para evitar que as consultas sejam danificadas acidentalmente em outras páginas. Nós também verificamos para garantir que ambos possamos business como um elemento de taxonomy e um elemento de term também. (Nota: taxonomy e term são um par; eles são usados ​​juntos para permitir a consulta de um termo de taxonomia; tem que ter ambos ou o WordPress não sabe qual taxonomia inspecionar).

Você pode se perguntar como o business apareceu no elemento de taxonomy da matriz query_vars . O que escrevemos no nosso gancho parse_query desencadeou a magia interna do WordPress que foi colocada em espera quando você registrou a taxonomia ” business “, definindo query_var como verdadeiro ( register_taxonomy() copia o nome da taxonomia como sua query_var ; você pode alterá-la de Claro, mas a menos que você tenha um conflito, é melhor ficar com o mesmo):

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

Agora WordPress ‘$ wp_query foi escrito para usar slugs para consultas padrão de taxonomia filtrada, e não ID de termos de taxonomia. Para este caso de uso, o que realmente precisamos para fazer a nossa consulta de filtragem são estes:

taxonomy : negócio

term : business-1 (ou seja, o slug )

Não são estes:

taxonomy : negócio

term : 27 (ou seja, o term_id )

Curiosamente e, infelizmente, o menu suspenso gerado por wp_dropdown_categories() configura o atributo de value para o term_id do termo (/ business), não o termo slug . Por isso, precisamos converter $wp_query->query_vars['term'] de um term_id numérico para seu slug string como segue no snippet snagged from above (Observe que esta não é a maneira mais term_id de consultar um database, mas até que o WordPress adicione suporte para term_ids na sua consulta, é o melhor que podemos fazer!):

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

E é isso! Com essas duas funções você obtém a filtragem que deseja.


Fui em frente e adicionei uma coluna de “Negócios” à sua lista de listview porque, bem, eu sabia que seria sua próxima pergunta. Sem ter uma coluna para o que você filtra, pode ser muito confuso para o usuário final. (Eu lutou com isso sozinho, e eu era o codificador!) Você pode, claro, já ver a coluna “Negócios” nas capturas de canvas anteriores acima.

Passo # 3: O manage_posts_columns filtro.

Para adicionar uma coluna à lista de postagens, é necessário chamar dois (2) ganchos mais. O primeiro é manage_posts_columns ou a versão específica do tipo de publicação manage_listing_posts_columns que eu manage_listing_posts_columns . Ele aceita um parâmetro ( posts_columns ) e é chamado de /wp-admin/includes/template.php (na /wp-admin/includes/template.php que a chamada está na linha 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'] = 'Businesses'; return $new_posts_columns; } 

Sua function manage_posts_columns hook obtém uma matriz de colunas em que o valor é o header da coluna exibido e a chave é o identificador de coluna interno. Os identificadores de coluna padrão podem include estes e mais: 'cb' , 'title ‘, 'author' , “ ‘date’`, etc.

'cb' , é a coluna da checkbox e ambos 'title' e 'date' referem-se a post_title e post_date da tabela wp_posts , respectivamente. 'author' , é claro, é o campo post_author após o nome do autor ser recuperado da tabela wp_users .

Captura de tela da coluna 'cb' posts como caixa de seleção.

Para o gancho manage_posts_columns , simplesmente queremos inserir nossos businesses colunas na matriz $posts_columns antes do 'author' , assumindo que algum outro plugin ainda não removeu o author da lista.

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

( add_businesses_column_to_listing_list() como escrevi add_businesses_column_to_listing_list() ocorreu-me que o PHP deve ter uma maneira mais fácil de inserir um valor em uma matriz associativa na ordem correta?!? Ou, pelo menos, tem que haver uma function no núcleo do WordPress para fazê-lo? Mas desde que Google me decepcionou, então eu fui com o que funcionou. Se alguém tiver alguma alternativa sugerida, eu serei todos os ouvidos e aprecio com antecedência!)

O que finalmente nos leva a …

Etapa # 4: O manage_posts_custom_column

A segunda coisa de dois (2) que precisamos fazer para que nossos negócios sejam exibidos na coluna é realmente enviar o nome de cada uma das empresas associadas usando o gancho de ação manage_posts_custom_column . Este gancho aceita dois (2) parâmetros ( column_id e post_id ) e também é chamado de /wp-admin/includes/template.php (na /wp-admin/includes/template.php que a chamada está na linha 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] = '' . $business->name . ''; } //echo implode("
",$businesses); echo implode(' | ',$businesses); } break; } } }

Este gancho é chamado para cada coluna para cada linha de postagem (/ business). Primeiro, verificamos que estamos realmente trabalhando com apenas o tipo de postagem personalizado e, em seguida, usamos uma instrução switch para testar contra o column_id . Eu escolho switch porque este gancho é freqüentemente usado para gerar saída para muitas colunas diferentes, especialmente se usarmos uma function para vários tipos de postagem diferentes que podem parecer algo como isto:

 < ?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 '...whatever...'; break; case 'listing:property': echo '...whatever...'; break; case 'agent:listing': echo '...whatever...'; break; } } 

Inspecionando nosso caso de uso um pouco mais perto, você vê a function get_the_terms() que simplesmente retorna a lista de termos para esta taxonomia (ou seja, empresas para essa listview). Aqui, obtenha o permalink para a página de front-end do termo que normalmente lista mensagens que estão associados ao termo, mas é claro que podem variar de acordo com o tema e / ou os plugins instalados.

Usamos o permalink para hiperligar o termo apenas porque eu gosto de hiperlinks coisas. Em seguida, juntamos todos os termos com hiperlinks (/ empresas) juntos separados com o caractere pipe (' | ') e saída para o buffer PHP que o envia para o navegador do usuário / cliente HTTP:

 < ?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] = '' . $business->name . ''; } //echo implode("
",$businesses); echo implode(' | ',$businesses); }

AGORA , finalmente terminamos.


Então, em resumo, você precisa usar os seguintes quatro (4) ganchos para obter um filtro e uma coluna relacionada na página da lista de postagens personalizadas (Oh, também funcionará com Posts e Pages). Eles são:

  • Etapa # 1: O gancho de ação restrict_manage_posts .
  • Etapa 2: o filtro de filtragem parse_query .
  • Passo # 3: O manage_posts_columns filtro.
  • Etapa # 4: O manage_posts_custom_column

Onde baixar o código

Mas se eu forçei você a ler todos os itens acima, então eu certamente não seria uma pessoa muito legal, se eu também fizesse você descobrir o código apenas para poder experimentá-lo! Mas ao contrário do que algumas pessoas dizem, eu sou legal. Então, vá lá:

NOTA para @tarasm : incluí ganchos para register_post_type() e register_taxonomy() para que outros possam tentar isso sem ter que recriá-los. Você provavelmente deseja excluir essas duas chamadas de function antes de testar isso.


Resposta Original:

Olá @tarasm :

Você está procurando um menu suspenso no topo, como essa canvas ou você está procurando uma gota abaixo por registro de postagem e, em caso afirmativo, como você esperaria que o último funcionasse?

Como criar a funcionalidade Classificar por um tipo de postagem personalizado no administrador do WordPress

Se o primeiro, dê uma olhada nesta resposta à pergunta. Como classificar a área de administração de um tipo de postagem personalizado do WordPress por um campo personalizado? Se for isso que você precisa, posso fornecer mais detalhes relacionados à taxonomia.

Just wanted to share an alternative implementation. I didn’t have Mike’s incredible tutorial when I was figuring this out, so my solution is a little different. Specifically, I’m going to simplify Mike’s step #1 and eliminate step #2 – the other steps are still applicable.

In Mike’s tutorial, using wp_dropdown_categories() saves us some manual list-building, but requires some complicated conditional query modification ( step #2 ) to handle its use of ID instead of slug. Not to mention the difficulty of modifying that code to deal with other scenarios, like multiple taxonomy filters..

Another approach is to simply not use the flawed wp_dropdown_categories() at all, but instead to build our own dropdown select lists from scratch. It’s not that complicated, takes less than 30 lines of code, and doesn’t require hooking parse_query at all:

 add_action( 'restrict_manage_posts', 'my_restrict_manage_posts' ); function my_restrict_manage_posts() { // only display these taxonomy filters on desired custom post_type listings global $typenow; if ($typenow == 'photos' || $typenow == 'videos') { // create an array of taxonomy slugs you want to filter by - if you want to retrieve all taxonomies, could use get_taxonomies() to build the list $filters = array('plants', 'animals', 'insects'); foreach ($filters as $tax_slug) { // retrieve the taxonomy object $tax_obj = get_taxonomy($tax_slug); $tax_name = $tax_obj->labels->name; // retrieve array of term objects per taxonomy $terms = get_terms($tax_slug); // output html for taxonomy dropdown filter echo ""; } } } 

By simply plugging the desired taxonomies into the $filters array, you can quickly output multiple taxonomy filters. They appear exactly the same as those in Mike’s screenshots. Then you can follow through with step #3 and #4 .

Here is a version of this that automatically creates and applies filters from all taxonomies that apply to all custom post types which use them. (what a mouthful) Anyways, I also tweaked it so it works with wp_dropdown_categories() and wordpress 3.1. The project I’m working on is called ToDo, you can rename the functions to something that makes sense for you, but this should pretty much work for everything automatically.

 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' => __('Show All '.$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'); 

Note that I’m using a plugin that adds ‘term_order’ as a way to order terms, you’ll have to change that, or remove that argument to fallback to the default.

Late answer


I’ve written Filterama , a plugin that will add this functionality the easiest possible way.

Update for WordPress 3.5+

Now that things are much easier, here’s a very simple solution as plugin or mu-plugin.

It uses as less resources as possible, loads only on the needed screens and adds Columns + Filters for every custom taxonomy.

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

And then you just need a customized Walker class.

 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( ' ', $depth * 3 ); $cat_name = apply_filters( 'list_cats', $term->name, $term ); $output .= sprintf( '', $depth, $term->slug, selected( $args['selected'], $term->slug, false ), $pad.$cat_name, $args['show_count'] ? "  ({$term->count})" : '' ); } } 

I just wanted to make a quick note. On newer versions of WP, post listings on admin are handled by the WP_Posts_List_Table class. The apply_filters code is now as follows:

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

So to add new columns an add_filter hook should be like this:

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

Here goes an example:

 function my_add_columns($posts_columns, $post_type) { if ('myposttype' == $post_type) { $posts_columns = array( "cb" => "", "title" => "Title", "anothercolumn" => "Bacon", "date" => __( 'Date' ) ); return $posts_columns; } } 

Now, for the post rows. This is the code that handles column data on the listings:

 default: ?> >< ?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 ); ?> < ?php 

In order to retrieve our posts data, we have to add an action hook like this:

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

Example (this example uses taxonomies, but you could query any other stuff):

 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] = '' . $flavour->name . ''; } echo implode(' | ',$flavours); } break; default: break; } } 


custom_post_type: books custom_taxonomy: genre

Only modify were it says: // 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' => __("Show All {$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'); 

Here’s a way to do it using the restrict_manage_posts action. It seems to work well for me and adds the ability to filter by taxonomy for all post types and there related taxonomies.

 // registers each of the taxonomy filter drop downs function sunrise_fbt_add_taxonomy_filters() { global $typenow; // the current post type $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) { //Check if hierarchical - if so build hierarchical drop-down if($tax->hierarchical) { $args = array( 'show_option_all' => 'All '.$tax->labels->name, 'show_option_none' => 'Select '.$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 ""; } } } } } add_action( 'restrict_manage_posts', 'sunrise_fbt_add_taxonomy_filters', 100 ); /** * Create HTML dropdown list of Categories. * * @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(' ', $depth * 3); $cat_name = apply_filters('list_cats', $category->name, $category); $output .= "\t\n"; } } 

One note – I tried restricting the depth because some of my hierarchical taxonomies are quite large but it didn’t work – could be a bug in the wp_dropdown_categories function?

Hierarchical version of @sumtic’s answer, as requested by @kevin:

 < ?php add_action( 'restrict_manage_posts', 'my_restrict_manage_posts' ); function my_restrict_manage_posts() { // only display these taxonomy filters on desired custom post_type listings global $typenow; if ($typenow == 'photos' || $typenow == 'videos') { // create an array of taxonomy slugs you want to filter by - if you want to retrieve all taxonomies, could use get_taxonomies() to build the list $filters = array('plants', 'animals', 'insects'); foreach ($filters as $tax_slug) { // retrieve the taxonomy object $tax_obj = get_taxonomy($tax_slug); $tax_name = $tax_obj->labels->name; // output html for taxonomy dropdown filter echo ""; } } } 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 each select option line, check against the last $_GET to show the current option selected echo ' 

I basically removed the code that created the options and put that in it’s own function. The function ‘generate_taxonomy_options’, in addition of taking the tax_slug, also takes a parent and level parameter. The function assumes that its creating options for the parent 0, which will select all the root level terms. In the loop the function will recursively call itself, using that current term as a parent and increasing the level by one. It automatically adds ticks to the side the deeper you go down the tree and voila!

Update of @Drew Gourley’s answer for WP 3.3.1 (and incorporating code from ):

 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' => __('Show All '.$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() )); } } } //Dropdown filter class. Used with wp_dropdown_categories() to cause the resulting dropdown to use term slugs instead of ids. class DropdownSlugWalker extends Walker_CategoryDropdown { function start_el(&$output, $category, $depth, $args) { $pad = str_repeat(' ', $depth * 3); $cat_name = apply_filters('list_cats', $category->name, $category); $output .= "\t\n"; } } 

Apologies for the fact that, as a new user, I can’t post comments but I can post an answer…

As of WordPress 3.1 (RC 1) Mike’s answer (which has served me so well for the past couple for months) no longer works for me; restricting by any taxonomy child gives an empty result. I tried Somatic’s update and it worked great; even better, it works with multiple taxonomy queries which has been worked into this release.

Just tried both codes, from Mike and sumtic and was wondering on how to get one thing from each technique:

With Mike’s code, it shows the dropdown list with the hierarchical option, which helps a lot. But in order to display two dropdowns i had to duplicate the if ($typenow=='produtos') {...} statement in the function restrict_listings_by_business() and also the if ($pagenow=='edit.php' && ... } in the convert_business_id_to_taxonomy_term_in_query($query) function which now gives a lot of code.

With sumtic’s code i just need to specify the taxonomies i’d like to see as dropdowns and bam, works; $filters = array('taxo1', 'taxo2');

Question: can i get sumtic’s approach and also have the hierarchical option?

Thanks a lot anyway for this tutorial, helped a lot!

Mike’s tutorial on this is great! I probably would not have bothered adding this functionality to my Media Categories plugin if I would have had to figure it out on my own.

That said, I think using parse_query and then get then query for the term isn’t necessary. It’s cleaner for create your own custom walker class. Maybe that wasn’t possible when he wrote his post – its 3 years old at the time of my writing this.

Checkout this great snippet on github. Works like a charm, changes the ID’s in the dropdown values into slugs, so it just works natively without modifying the query.

This is not well known I guess, but as of wordpress 3.5, you can pass 'show_admin_column' => true to register_taxonomy . This does 2 things:

  1. Adds the taxonomy column to the admin post type list view
  2. By clicking the name of the term on the taxonomy column, it will in fact filter the list to that term .

So, not exactly the same as having a select, but almost the same functionality, width just one row of code.

Also, as you can read, there is a new filter tailored for manual adding taxonomy column (if you really need to).