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


129

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

Aqui está a aparência dessa funcionalidade na lista de administradores das Postagens (eu gostaria do mesmo para o meu Tipo de postagem personalizada):

Categorias Dropdown in Posts

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

<?php
/*
Plugin Name: Listing Content Item
Plugin URI:
Description: 
Author: 
Version: 1.0
Author URI: 
*/

class Listing {
  var $meta_fields = array("list-address1","list-address2","list-country","list-province","list-city","list-postcode","list-firstname","list-lastname","list-website","list-mobile","list-phone","list-fax","list-email", "list-profile", "list-distributionrange", "list-distributionarea");

  public function loadStyleScripts() {
    $eventsURL = trailingslashit( WP_PLUGIN_URL ) . trailingslashit( plugin_basename( dirname( __FILE__ ) ) ) . 'css/';
    wp_enqueue_style('listing-style', $eventsURL.'listing.css');
  }

  function Listing() {
    // Register custom post types
    register_post_type('listing', array(
      'labels' => 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" => "<input type=\"checkbox\" />",
      "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]."<br />";
        if(isset($custom["list-lastname"][0])) echo $custom["list-lastname"][0]."<br />";
        if(isset($custom["list-email"][0])) echo $custom["list-email"][0]."<br />";
        if(isset($custom["list-website"][0])) echo $custom["list-website"][0]."<br />";
        if(isset($custom["list-phone"][0])) echo $custom["list-phone"][0]."<br />";
        if(isset($custom["list-mobile"][0])) echo $custom["list-mobile"][0]."<br />";
        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]."<br />";
        if(isset($custom["list-address2"][0])) echo $custom["list-address2"][0]."<br />";
        if(isset($custom["list-city"][0])) echo $custom["list-city"][0]."<br />";
        if(isset($custom["list-province"][0])) echo $custom["list-province"][0]."<br />";
        if(isset($custom["list-postcode"][0])) echo $custom["list-postcode"][0]."<br />";
        if(isset($custom["list-country"][0])) echo $custom["list-country"][0]."<br />";
        if(isset($custom["list-profile"][0])) echo $custom["list-profile"][0]."<br />";
        if(isset($custom["list-distributionrange"][0])) echo $custom["list-distributionrange"][0]."<br />";
        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, '<a href="' . get_term_link($speaker->slug, 'businesses') . '">' . $speaker->name . '</a>');
          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 = '';
?>
<div class="personal">
<table border="0" id="personal">
<tr><td class="personal_field"><label>Firstname:</label></td><td class="personal_input"><input name="list-firstname" value="<?php echo $first_name; ?>" /></td></tr>
<tr><td class="personal_field"><label>Lastname:</label></td><td class="personal_input"><input name="list-lastname" value="<?php echo $last_name; ?>" /></td></tr>
<tr><td class="personal_field"><label>Email:</label></td><td class="personal_input"><input name="list-email" value="<?php echo $email; ?>" size="40"/></td></tr>
<tr><td class="personal_field"><label>Website:</label></td><td class="personal_input"><input name="list-website" value="<?php echo $website; ?>" size="40"/></td></tr>
<tr><td class="personal_field"><label>Phone:</label></td><td class="personal_input"><input name="list-phone" value="<?php echo $phone; ?>" /></td></tr>
<tr><td class="personal_field"><label>Mobile:</label></td><td class="personal_input"><input name="list-mobile" value="<?php echo $mobile; ?>" /></td></tr>
<tr><td class="personal_field"><label>Fax:</label></td><td class="personal_input"><input name="list-fax" value="<?php echo $fax; ?>" /></td></tr>
</table>
</div>
     <?php
  }

  // Admin post meta contents
  function meta_location() {
    global $post;
    $custom = get_post_custom($post->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 = '';
  ?>
<div class="location">
<table border="0" id="location">
<tr><td class="location_field"><label>Address 1:</label></td><td class="location_input"><input name="list-address1" value="<?php echo $address1; ?>" size="60" /></td></tr>
<tr><td class="location_field"><label>Address 2:</label></td><td class="location_input"><input name="list-address2" value="<?php echo $address2; ?>" size="60" /></td></tr>
<tr><td class="location_field"><label>City:</label></td><td class="location_input"><input name="list-city" value="<?php echo $city; ?>" /></td></tr>
<tr><td class="location_field"><label>Province:</label></td><td class="location_input"><input name="list-province" value="Ontario" readonly /></td></tr>
<tr><td class="location_field"><label>Postal Code:</label></td><td class="location_input"><input name="list-postcode" value="<?php echo $post_code; ?>" /></td></tr>
<tr><td class="location_field"><label>Country:</label></td><td class="location_input"><input name="list-country" value="Canada" readonly /></td></tr>
<tr><td class="location_field"><label>Profile:</label></td><td class="location_input"><input name="list-profile" value="<?php echo $profile; ?>" size="60" /></td></tr>
<tr><td class="location_field"><label>Distribution Range:</label></td><td class="location_input"><input name="list-distributionrange" value="<?php echo $distribution_range; ?>" size="60" /></td></tr>
<tr><td class="location_field"><label>Distribution Area:</label></td><td class="location_input"><input name="list-distributionarea" value="<?php echo $distribution_area; ?>" size="60" /></td></tr>
</table>
</div>
   <?php
  }
}

// Initiate the plugin
add_action("init", "ListingInit");
function ListingInit() { 
  global $listing;
  $listing = new Listing();
  $add_css = $listing->loadStyleScripts();
}

Como posso adicionar uma lista suspensa de empresas à lista de administradores das listagens?


8
Obrigado pela captura de tela, realmente ajuda a tê-las.
MikeSchinkel

Existe um plugin Admin Taxonomy Filter que pode fazer o trabalho exato.
Anh Tran

Respostas:


140

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


Olá @tarasm :

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

As capturas de tela:

... vamos ver algumas capturas de tela do produto acabado:

Página da lista de listagens sem filtragem:

Página da lista de listagens sem filtragem
(fonte: mikeschinkel.com )

Página de listagem de listagens Com filtragem:

Página de listagem de listagens Com filtragem
(fonte: mikeschinkel.com )

O código

Então, aqui vamos nós ... ( Nota: usei uma forma singular para o nome da taxonomia de business; espero que corresponda ao seu. Com muita experiência com o WordPress e o desenvolvimento de bancos de dados no passado, acredito que seja melhor fazê-lo dessa maneira .)

Etapa 1: o restrict_manage_postsgancho de ação.

A primeira coisa que você precisa fazer é conectar a restrict_manage_postsação que não possui parâmetros e é chamada a partir /wp-admin/edit.php(na v3.0.1, a chamada está na linha 378.) Isso permitirá gerar a seleção suspensa no local apropriado acima da lista de Listando 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 verificando a $typenowvariável para garantir que estamos de fato em um post_typede listing. Caso contrário, você receberá essa lista suspensa para todos os tipos de postagem que, em alguns casos, é o que você deseja, mas não neste caso.

Em seguida, carregamos informações sobre a taxonomia comercial usando get_taxonomy(). Precisamos recuperar o rótulo da taxonomia (ou seja, " Negócios "; poderíamos ter codificado, mas isso não é muito bom se você precisar internacionalizar mais tarde.) Em seguida, chamamos wp_dropdown_categories()todos os argumentos apropriados na $argsmatriz para gerar o 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? Vamos olhar para cada um individualmente:

  • show_optional_all- Bem direto, é o que é exibido no menu suspenso primeiro e quando não há filtragem aplicada. No nosso caso, será "Mostrar todas as empresas ", mas poderíamos chamá-lo de "Listagens para todas as empresas" ou o que você quiser.

  • taxonomy- Esses argumentos informam à função de que taxonomia extrair termos, mesmo que a função tenha categoriesem seu nome. Na v2.8 e anterior, o WordPress não tinha taxonomias personalizadas, mas quando elas foram adicionadas, a equipe decidiu que seria mais fácil adicionar um argumento de taxonomia a essa função do que criar outra função com outro nome.

  • name- Este argumento permite especificar o valor que o WordPress usa para o nameatributo do elemento <select> gerado para o menu suspenso. Caso não seja óbvio, esse também é o valor que será usado na URL ao filtrar.

  • orderby- Este argumento diz ao WordPress como ordenar os resultados em ordem alfabética. No nosso caso, especificamos para comprar os nametermos da taxonomia, ou seja, os nomes das empresas nesse caso.

  • selected- Este argumento é necessário para que o menu suspenso possa mostrar o filtro atual no menu suspenso. Deve ser do term_idtermo de taxonomia selecionado. No nosso caso, pode ser term_iddo "Business # 2" . Onde conseguimos esse valor? Da variável global do WordPress $wp_query; ele possui uma propriedade queryque contém uma matriz de todos os parâmetros da URL e seus valores (a menos que algum plugin rebelde o tenha modificado, é claro.) Dado como o WordPress processa as coisas, haverá um termparâmetro da URL passado na URL quando o usuário clicar no filtro botão se o usuário selecionou um termo válido (ou seja, uma das empresas listadas).

  • hierarchical- Ao definir isso para truevocê informar à função que respeite a natureza hierárquica da taxonomia e exibi-los em uma exibição em árvore, se os termos (negócios) tiverem filhos. Para uma captura de tela para ver como é isso, veja abaixo.

  • depth- Esse argumento colabora com o hierarchicalargumento para determinar quantos níveis de profundidade a função deve exibir na exibição de filhos.

  • show_count- Se trueesse argumento exibir uma contagem de postagens entre parênteses à esquerda do nome do termo na lista suspensa. Nesse caso, seria exibida uma contagem de listagens associadas a uma empresa. Para uma captura de tela para ver como é isso, veja abaixo.

  • hide_empty- Por fim, se houver termos na taxonomia que não estejam associados a uma postagem (ou seja, empresas não associadas a uma listagem), definir isso para trueomitir a inclusão na lista suspensa.

O menu suspenso Taxonomia deve hierarquizar e contar
(fonte: mikeschinkel.com )

Etapa 2: o parse_querygancho do filtro.

Em seguida, chamamos nossa atenção para o parse_querygancho de filtro que possui um parâmetro ( $query) e é chamado /wp-includes/query.php(na v3.0.1, essa chamada está na linha 1549). É chamado quando o WordPress termina de inspecionar a URL e definir todos os valores apropriados no momento. ativo, $wp_queryincluindo coisas como $wp_query->is_homee $wp_query->is_authoretc.

Depois que o parse_querygancho do filtro for executado, o WordPress chamará get_posts()e carregará uma lista de postagens com base no que está especificado no ativo atualmente $wp_query. Por isso, parse_querymuitas vezes é um ótimo lugar para fazer o WordPress mudar de idéia sobre quais postagens serão carregadas.

No seu caso de uso, queremos que o WordPress filtre com base nas empresas selecionadas; ou seja, para exibir apenas as listagens que foram associadas à empresa selecionada (eu diria "... somente as listagens que foram " categorizadas " pela empresa selecionada", mas isso não é técnico correto); categoryé a própria taxonomia entre pares com a businessexceção de que categoryestá embutido no WordPress e businessé personalizado. Mas, para aqueles familiarizados com a categorização de postagens, isso pode ajudá-lo a entender, pois eles funcionam quase de forma idêntica. Mas discordo ...)

Para o código. A primeira coisa que fazemos é pegar uma referência aos ativos atualmente $wp_query, query_varspara que seja mais conveniente trabalhar, assim como é feito na parse_query()função do WordPress . Diferente do $wp_query->queryque é usado para espelhar os parâmetros passados ​​no URL, a $wp_query->query_varsmatriz é usada para controlar a consulta que o WordPress executa e espera-se que seja modificada. Portanto, se você precisar modificar um, seria esse (pelo menos eu acho que é o diferente entre os dois; se alguém souber de outra forma, 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, testamos $pagenowpara garantir que estamos realmente carregando o WordPress a partir do caminho da URL /wp-admin/edit.php. Fazemos isso para não estragar as consultas acidentalmente em outras páginas. Também verificamos se temos tanto businessum taxonomyelemento quanto um termelemento. (Observe taxonomye termsão um par; eles são usados ​​juntos para permitir a consulta de um termo de taxonomia; é preciso ter os dois ou o WordPress não sabe qual taxonomia inspecionar.)

Você pode se perguntar como businessapareceu no taxonomyelemento da query_varsmatriz. O que escrevemos em nosso parse_querylivro desencadeou a magia interna do WordPress que estava em espera quando você registrou a businesstaxonomia " " definindo- query_vara como verdadeira ( register_taxonomy()copia o nome da taxonomia como sua query_var; você pode alterá-la, é claro, mas a menos que 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, o $ wp_query do WordPress foi escrito para usar slugs em consultas filtradas por taxonomia padrão, e não em IDs de termos de taxonomia. Para este caso de uso, o que realmente precisamos para que nossa consulta de filtragem funcione são:

taxonomy: negócios

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

Não estes:

taxonomy: negócios

term: 27 (ie term_id)

Curiosamente e infelizmente, o menu suspenso gerado por wp_dropdown_categories()define o atributo <option>'s valuepara o termo (/ comercial') term_id, não para o termo slug. Portanto, precisamos converter $wp_query->query_vars['term']de um numérico term_idpara sua sequência da slugseguinte forma no snippet capturado acima (Observe que essa não é a maneira mais eficiente de consultar um banco de dados, mas até que o WordPress adicione suporte a term_ids em 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.

MAS ESPERE, HÁ MAIS! :-)

Fui em frente e adicionei uma coluna "Empresas" à sua lista de listagens porque, bem, eu sabia que essa seria sua próxima pergunta. Sem ter uma coluna para o que você filtra, pode ser muito confuso para o usuário final. (Eu mesmo lutei com ele e fui o codificador!) É claro que você já pode ver a coluna "Negócios" nas capturas de tela anteriores acima.

Etapa 3: o manage_posts_columnsgancho do filtro.

Para adicionar uma coluna à lista de postagens, é necessário chamar mais dois (2) ganchos. O primeiro é manage_posts_columnsou a versão específica do tipo de postagem manage_listing_posts_columnsque chamei. Ele aceita um parâmetro ( posts_columns) e é chamado de /wp-admin/includes/template.php(na v3.0.1, essa 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 manage_posts_columnsfunção de gancho recebe uma matriz de colunas em que o valor é o cabeçalho da coluna exibido e a chave é o identificador interno da coluna. Identificadores de coluna padrão pode incluir estes e mais: 'cb', 'title' 'author', ``' date'`, etc.

'cb', é a checkboxcoluna e ambos 'title'e se 'date'referem a post_titlee post_dateda wp_poststabela, respectivamente. 'author'é claro que é o post_authorcampo após o nome do autor ser recuperado da wp_userstabela.

Captura de tela da coluna de postagens 'cb' como uma caixa de seleção.
(fonte: mikeschinkel.com )

Para o manage_posts_columnsgancho, estamos simplesmente querendo inserir nossa coluna businessesna $posts_columnsmatriz antes 'author', assumindo que algum outro plugin ainda não tenha sido removido authorda lista!

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

( Observe que, como escrevi add_businesses_column_to_listing_list(), me ocorreu que o PHP deve ter uma maneira mais fácil de inserir um valor em uma matriz associativa na ordem correta?!? Ou pelo menos deve haver uma função no núcleo do WordPress para fazer isso? Mas como o Google decepcione-me, então fui com o que funcionou. Se alguém tiver alguma alternativa sugerida, serei todo ouvidos e agradecemos antecipadamente!)

O que finalmente nos leva a ...

Etapa 4: o manage_posts_custom_columngancho de ação

A segunda coisa de dois (2) que precisamos fazer para que nossos negócios sejam exibidos na coluna é realmente gerar o nome de cada um dos negócios associados usando o manage_posts_custom_columngancho de ação. Esse gancho aceita dois (2) parâmetros ( column_ide post_id) e também é chamado de /wp-admin/includes/template.php(na v3.0.1, 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] = '<a href="'.$edit_link.'">' . $business->name . '</a>';
                }
                //echo implode("<br/>",$businesses);
                echo implode(' | ',$businesses);
            }
            break;
        }
    }
}

Esse gancho é chamado para cada coluna para cada linha de postagem (/ comercial). Primeiro, verificamos que estamos realmente trabalhando apenas com o listingtipo de postagem personalizada e, em seguida, usamos uma switchinstrução para testar o column_id. Eu escolhi switchporque esse gancho é frequentemente usado para gerar saída para muitas colunas diferentes, especialmente se usarmos uma função para muitos tipos diferentes de postagem, que podem ser 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 get_the_terms()função que simplesmente retorna a lista de termos para esta taxonomia (ou seja, empresas para esta listagem). Veja aqui o link permanente para a página da web de front-end do termo que normalmente lista as postagens associadas com o termo, mas é claro que isso pode ser diferente, dependendo do tema e / ou plug-ins instalados.

Usamos o link permanente para vincular o termo apenas porque gosto de vincular coisas. Em seguida, mesclamos todos os termos com hiperlink (/ business) juntos, separados pelo caractere pipe (' |') e emitimos para o buffer PHP que o envia ao navegador / cliente HTTP do usuário:

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

Agora estamos finalmente prontos.

Sumário

Portanto, em resumo, você precisa usar os quatro (4) ganchos a seguir para obter um filtro e uma coluna relacionada na página de lista de postagens personalizada (Ah, ele também funcionará com Postagens e Páginas.) São elas:

  • Etapa 1: o restrict_manage_postsgancho de ação.
  • Etapa 2: o parse_querygancho do filtro.
  • Etapa 3: o manage_posts_columnsgancho do filtro.
  • Etapa 4: o manage_posts_custom_columngancho de ação

Onde baixar o código

Mas se eu forçar você a ler todas as opções acima, certamente não seria uma pessoa muito legal se eu também fizesse você desenterrar o código apenas para poder testá-lo! Mas, ao contrário do que algumas pessoas dizem, eu sou legal. Então aqui vai você:

NOTA para @tarasm : incluí ganchos pararegister_post_type()eregister_taxonomy()para que outros pudessem experimentar isso sem ter que recriá-los. Você provavelmente desejará excluir essas duas chamadas de função antes de testar isso.

O FIM


Resposta original:

Olá @tarasm :

Você está procurando uma lista suspensa na parte superior como esta tela ou está procurando uma lista suspensa por registro de postagem e, em caso afirmativo, como espera que o último funcione?

Como criar a funcionalidade Classificar por para um tipo de postagem personalizado no WordPress Admin
(fonte: mikeschinkel.com )

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


Estou procurando uma lista suspensa na parte superior que mostre o filtro Categorias. Fiquei perambulando se existe uma maneira padrão de fazer isso sem ter que escrever código personalizado.
Taras Mankovski

À primeira vista, acho que você não pode fazer código personalizado sem o código, mas não acho que o código personalizado seja significativo. Eu tenho uma ligação com o cliente para me preparar, então terá que ser mais tarde hoje.
MikeSchinkel

2
Na verdade, ambas as soluções (somática e MikeSchinkel) não estão funcionando quando você tenta filtrar 2 taxonomia diferente no mesmo filtro: - / Sempre filtrando a taxonomia mais recente ao tentar filtrar 2+ ao mesmo tempo.
Ünsal Korkmaz

1
@ Ünsal A versão atual do WordPress (3.0) não suporta várias consultas de taxonomia, mas pelo que ouvi dizer, isso mudará na versão 3.1. Para que este exemplo funcione com várias taxonomias, você precisará adicionar algumas junções e locais à consulta por meio dos ganchos de filtro Posts_join e posts_where.
Manny Fleurmond

1
No WP 3.1+, as etapas 1 e 2 são melhores na resposta @ drew-gourley (na verdade, sua etapa 2 não funcionou para mim, acho que há mudanças nessa filtragem no novo WordPress).
Tomasz Struczyński

44

Só queria compartilhar uma implementação alternativa. Eu não tinha o tutorial incrível de Mike quando estava pensando nisso, então minha solução é um pouco diferente. Especificamente, vou simplificar a etapa 1 de Mike e eliminar a etapa 2 - as outras etapas ainda são aplicáveis.

No tutorial de Mike, o uso wp_dropdown_categories()economiza um pouco de criação manual de listas, mas requer algumas modificações complicadas de consulta condicional ( etapa 2 ) para lidar com o uso de ID em vez de slug. Sem mencionar a dificuldade de modificar esse código para lidar com outros cenários, como vários filtros de taxonomia.

Outra abordagem é simplesmente não usar as falhas wp_dropdown_categories(), mas criar nossas próprias listas suspensas do zero. Não é tão complicado, requer menos de 30 linhas de código e não requer conexão parse_query:

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 "<select name='$tax_slug' id='$tax_slug' class='postform'>";
            echo "<option value=''>Show All $tax_name</option>";
            foreach ($terms as $term) {
                // output each select option line, check against the last $_GET to show the current option selected
                echo '<option value='. $term->slug, $_GET[$tax_slug] == $term->slug ? ' selected="selected"' : '','>' . $term->name .' (' . $term->count .')</option>';
            }
            echo "</select>";
        }
    }
}

Simplesmente conectando as taxonomias desejadas à $filtersmatriz, você pode gerar rapidamente vários filtros de taxonomia. Eles parecem exatamente os mesmos das capturas de tela de Mike. Depois, você pode seguir com as etapas 3 e 4 .


4
@somatic - Boa atualização! Sim, o uso wp_dropdown_categories()requer várias soluções alternativas. Tento manter as funções principais sempre que possível, mas, como você aponta, às vezes é preciso mais trabalho dessa maneira. Isso só prova que, com o WordPress, muitas vezes há mais de uma boa maneira de resolver um problema. Bom trabalho!
MikeSchinkel

Apenas parei de trabalhar para mim no WordPress 3.1. Tentando descobrir o que exatamente mudou. Parece que ele ainda deve funcionar: a taxonomia e lesmas prazo mostram-se como valores GET na URL, mas tudo o que resulta em é 0
Manny Fleurmond

Eu tenho tentado fazer isso funcionar, mas a única maneira que pude foi usar o gancho parse_query, verificar a var da consulta da taxonomia e definir os vars de consulta da taxonomia e do termo com base nisso. Usando o WP 3.1. A taxonomia e o termo devem aparecer no URL quando o filtro é enviado?
22411 sanchothefat

2
Funciona como um encanto para mim! Solução muito elegante mesmo. Devo-lhe a :) cerveja
Michal Mau

@somatic Isso funciona muito bem, mas existe uma maneira de fazer com que $ term-> count conte apenas os termos desse tipo de postagem? Por exemplo, se eu tiver uma taxonomia personalizada para fotos e vídeos, ele me mostrará, ao ver as postagens personalizadas dos vídeos, digite o número total de postagens para esse termo nos dois tipos de postagens personalizadas, em vez de apenas o número total de postagens de vídeo que usam essa postagem. prazo.
Greenhoe

13

Aqui está uma versão disso que cria e aplica automaticamente filtros de todas as taxonomias que se aplicam a todos os tipos de postagem personalizados que os utilizam. (que boca cheia) De qualquer forma, eu também o aprimorei para que funcione com wp_dropdown_categories () e wordpress 3.1. O projeto em que estou trabalhando se chama ToDo. Você pode renomear as funções para algo que faça sentido para você, mas isso deve funcionar para tudo 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' => __('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');

Observe que estou usando um plug-in que adiciona 'term_order' como uma maneira de solicitar termos, você precisará alterar isso ou remover esse argumento para retornar ao padrão.


muito sexy mesmo. Eu estava recebendo avisos de erro, então mudei if (isset ($ var)) para if (isset ($ var) && $ var> 0) para evitar tentar encontrar termos associados ao valor 0 de Exibir todos. Ah, e eu tive que voltar $ consulta na função todo_convert_restrict
helgatheviking

11

Resposta atrasada

Editar

Eu escrevi o Filterama , um plugin que adicionará essa funcionalidade da maneira mais fácil possível.

Atualização para WordPress 3.5+

Agora que as coisas estão muito mais fáceis, aqui está uma solução muito simples como plugin ou mu-plugin.

Utiliza o menor número possível de recursos, carrega apenas nas telas necessárias e adiciona Colunas + Filtros para cada taxonomia personalizada.

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 então você só precisa de uma classe Walker personalizada.

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})"
                : ''
        );
    }
}

Deu um giro nisso, mas o método get_select () parece estar faltando.
Dave Romsey

@ goto10 Você estava certo. Atualizada. Btw: É mais fácil pegar o plugin vinculado. Ele estará disponível no repositório do plug-in em uma ou duas semanas. (Já confirmado).
kaiser

Eu tive que usar $this->setup_vars();no início public function setup(), a fim de ter "manage_taxonomies_for_{$this->post_type}_columns"trabalho
Christian

Mas poderia ser porque eu o uso em um tema function.php withadd_action( 'init', array( 'WCM_Admin_PT_List_Tax_Filter', 'init' ) );
Christian

@ Christian Este não é um material temático. Isso pertence a um plug-in e, como o código acima atualmente o suporta, muito antes do Temas serem carregados.
Kaiser

7

Eu só queria fazer uma anotação rápida. Nas versões mais recentes do WP, as listagens de postagem no admin são tratadas pela classe WP_Posts_List_Table. O código apply_filters agora é o seguinte:

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

Portanto, para adicionar novas colunas, um gancho add_filter deve ser assim:

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

Aqui está um exemplo:

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

Agora, para as linhas da postagem. Este é o código que manipula dados da coluna nas listagens:

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

Para recuperar os dados de nossas postagens, precisamos adicionar um gancho de ação como este:

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

Exemplo (este exemplo usa taxonomias, mas você pode consultar outras coisas):

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

7

OBRAS NO WP 3.2!

custom_post_type: livros custom_taxonomy: gênero

Apenas modifique onde diz: // alterar AQUI

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

Essa é uma solução fácil e agradável para o WP 3.2+.
Petermolnar

funciona, mas __("Show All {$info_taxonomy->label}")é uma maneira errada de usar seqüências de caracteres traduzíveis.
Mark Kaplun

2

Aqui está uma maneira de fazer isso usando a ação strict_manage_posts. Parece funcionar bem para mim e adiciona a capacidade de filtrar por taxonomia para todos os tipos de post e taxonomias relacionadas.

// 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 "<select name='".$tax->rewrite['slug']."' id='".$tax->rewrite['slug']."' class='postform'>";
                    echo "<option value=''>Show All ".$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 );

/**
 * 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('&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";
        }
} 

Uma observação - tentei restringir a profundidade porque algumas de minhas taxonomias hierárquicas são bastante grandes, mas não funcionaram - poderia ser um bug na função wp_dropdown_categories?


2

Isso não é bem conhecido, eu acho, mas a partir do wordpress 3.5, você pode passar 'show_admin_column' => truepara register_taxonomy. Isso faz duas coisas:

  1. Adiciona a coluna taxonomia à exibição de lista do tipo de postagem do administrador
  2. Ao clicar no nome do termo na coluna taxonomia, ele realmente filtrará a lista para esse termo .

Portanto, não é exatamente o mesmo que ter um select, mas quase a mesma funcionalidade, largura apenas uma linha de código.

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

Além disso, como você pode ler, há um novo filtro personalizado para adicionar manualmente a coluna de taxonomia (se você realmente precisar).


1

Versão hierárquica da resposta da @ somatic, conforme solicitado por @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 "<select name='$tax_slug' id='$tax_slug' class='postform'>";
            echo "<option value=''>Show All $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 each select option line, check against the last $_GET to show the current option selected
        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);
    }

}
?>

Eu basicamente removi o código que criou as opções e coloquei isso em sua própria função. A função 'generate_taxonomy_options', além de usar o tax_slug, também aceita um parâmetro pai e nível. A função assume que está criando opções para o pai 0, que selecionará todos os termos do nível raiz. No loop, a função se chamará recursivamente, usando esse termo atual como pai e aumentando o nível em um. Ele adiciona automaticamente carrapatos ao lado, quanto mais fundo você desce da árvore e pronto!


1

Atualização da resposta de @Drew Gourley para o WP 3.3.1 (e incorporando o código em 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' => __('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('&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";
    }
}

0

Desculpas pelo fato de que, como novo usuário, não posso postar comentários, mas posso postar uma resposta ...

A partir do WordPress 3.1 (RC 1), a resposta de Mike (que me serviu muito bem nos últimos dois meses) não funciona mais para mim; restringir por qualquer filho de taxonomia fornece um resultado vazio. Eu tentei a atualização do Somatic e funcionou muito bem; melhor ainda, ele trabalha com várias consultas de taxonomia que foram trabalhadas nesta versão.


Para a versão alguma razão de somática não quer trabalhar para 3.1
Manny Fleurmond

0

Apenas tentei os dois códigos, de Mike e somático, e estava pensando em como obter uma coisa de cada técnica:

Com o código de Mike, ele mostra a lista suspensa com a opção hierárquica , o que ajuda muito. Mas, para exibir duas listas suspensas, eu tive que duplicar a if ($typenow=='produtos') {...}instrução na função restrict_listings_by_business()e também if ($pagenow=='edit.php' && ... }na convert_business_id_to_taxonomy_term_in_query($query)função, que agora fornece muito código.

Com o código da sommatic, só preciso especificar as taxonomias que gostaria de ver como dropdowns e bam, funciona; $filters = array('taxo1', 'taxo2');

Pergunta: posso obter a abordagem da somática e também ter a opção hierárquica ?

De qualquer forma, muito obrigado por este tutorial, ajudou muito!


Se a minha resposta para uma solução hierárquica
Manny Fleurmond

0

O tutorial de Mike é ótimo! Provavelmente, eu não teria me incomodado em adicionar essa funcionalidade ao meu plug-in Categorias de Mídia se eu tivesse que descobrir isso sozinho.

Dito isto, acho que usar parse_querye, em seguida, obter consulta para o termo não é necessário. É mais limpo para criar sua própria classe de caminhante personalizado. Talvez isso não fosse possível quando ele escreveu seu post - ele tinha 3 anos na época em que escrevi isso.

Confira este ótimo snippet no github. Funciona como um encanto, altera os IDs nos valores suspensos em slugs, portanto, funciona de forma nativa sem modificar a consulta.

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.