it-swarm-es.com

¿Agregar un filtro de taxonomía a la lista de administradores para un tipo de publicación personalizada?

He creado un Tipo de publicación personalizada llamado 'listing' y he agregado una Taxonomía personalizada llamada 'businesses'. Me gustaría agregar una lista desplegable de Negocios a la lista de administradores para los Listados.

Así es como se ve esta funcionalidad en la lista de administradores para Publicaciones (Me gustaría lo mismo para mi tipo de publicación personalizada):

Categories Dropdown in Posts

Aquí está mi código actual ( Y aquí está el mismo código en 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();
}

¿Cómo puedo agregar una lista desplegable de negocios a la lista de administradores para los listados?

128
Taras Mankovski

ACTUALIZACIÓN: He incluido una nueva respuesta completa, pero aun así, he dejado mi respuesta original en la parte inferior a la que hacen referencia los primeros comentarios.


Hola @tarasm :

Aunque dije que no debería ser difícil es un poco complicado. Pero antes de profundizar en el código ...

Las capturas de pantalla:

... vamos a ver algunas capturas de pantalla para el producto terminado:

Página de la lista de listados con No Filtrado:

 Listings list page with No Filtering 
(fuente: mikeschinkel.com )

Lista de listados página Con Filtrado:

 Listings list page With Filtering 
(fuente: mikeschinkel.com )

El código

Así que aquí vamos ... ( Nota: Utilicé una forma singular para el nombre de taxonomía de business; espero que coincida con su. De mucha experiencia con WordPress y el desarrollo de bases de datos en el pasado, lo creo es mejor hacerlo de esta manera.)

Paso # 1: El gancho de acción restrict_manage_posts.

Lo primero que debe hacer es conectar la acción restrict_manage_posts que no tiene parámetros y se llama desde /wp-admin/edit.php (en v3.0.1 esa llamada está en la línea 378.) Esto le permitirá generar la selección desplegable en la ubicación apropiada sobre la Lista de publicaciones de listado.

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

Comenzamos marcando la variable $typenow para asegurarnos de que de hecho estemos en un post_type de listing. Si no lo hace, obtendrá este menú desplegable para todos los tipos de publicaciones, que en algunos casos es lo que desea, pero no en este caso.

A continuación, cargamos información sobre la taxonomía empresarial utilizando get_taxonomy(). Lo necesitamos para recuperar la etiqueta de la taxonomía (es decir, "Empresas"; podríamos tener un código rígido, pero eso no es muy bueno si necesitas internacionalizar más tarde). Luego llamamos wp_dropdown_categories() con todos los datos apropiados. argumentos en la matriz $args para generar el menú desplegable

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

¿Pero cuáles son los argumentos apropiados? Veamos cada uno individualmente:

  • show_optional_all- Bastante sencillo, es lo que se muestra en el menú desplegable al principio y cuando no se ha aplicado ningún filtro. En nuestro caso, va a ser "Mostrar todos los negocios" pero podríamos haberlo llamado "Listados para todos los negocios" o lo que quieras.

  • taxonomy- Este argumento le dice a la función de qué taxonomía extraer los términos aunque la función tenga categories en su nombre. En v2.8 y anteriores, WordPress no tenía taxonomías personalizadas, pero cuando se agregaron, el equipo decidió que sería más fácil agregar un argumento de taxonomía a esta función que crear otra función con otro nombre.

  • name- Este argumento le permite especificar el valor que WordPress usa para el atributo name del elemento <select> generado para el menú desplegable. En caso de que no sea obvio, este es también el valor que se utilizará en la URL al filtrar.

  • orderby- Este argumento le dice a WordPress cómo ordenar los resultados alfabéticamente. En nuestro caso, especificamos para comprar la name de los términos de la taxonomía, es decir, los nombres comerciales en este caso.

  • selected- Este argumento es necesario para que el desplegable pueda mostrar el filtro actual en el desplegable. Debe ser el term_id del término de taxonomía seleccionado. En nuestro caso, podría ser el term_id from "Business # 2". ¿De dónde obtenemos este valor? De la variable global de WordPress $wp_query; tiene una propiedad query que contiene una matriz de todos los parámetros de URL y sus valores (a menos que algún complemento rebelde ya la haya modificado). Dado que WordPress procesa las cosas, habrá un parámetro de term URL que se pasará a la URL cuando el usuario haga clic el botón de filtro si el usuario seleccionó un término válido (es decir, uno de los negocios listados).

  • hierarchical- Al establecer esto en true, le dice a la función que respete la naturaleza jerárquica de la taxonomía y la muestre en una vista de árbol si los términos (negocios) en realidad tienen hijos. Para una captura de pantalla para ver cómo se ve esto, vea a continuación.

  • depth- Este argumento colabora con el argumento hierarchical para determinar cuántos niveles de profundidad debe tener la función en la visualización de niños.

  • show_count- Si true este argumento mostrará un conteo de publicaciones entre paréntesis a la izquierda del nombre del término dentro del menú desplegable. En este caso, se mostraría un recuento de listados asociados con una empresa. Para una captura de pantalla para ver cómo se ve esto, vea a continuación.

  • hide_empty- Finalmente, si hay términos en la taxonomía que están no asociados con una publicación (es decir, empresas que no están asociadas con una lista), al establecer esto en true se omitirá su inclusión. en el desplegable.

 Taxonomy Drop Down should hierarchy and counts 
(fuente: mikeschinkel.com )

Paso # 2: El gancho del filtro parse_query.

Luego llamamos nuestra atención al gancho del filtro parse_query que tiene un parámetro ($query) y se llama desde /wp-includes/query.php (en v3.0.1 esa llamada está en la línea 1549.) Se llama cuando WordPress ha terminado de inspeccionar la URL y establecer todos los valores apropiados en el $wp_query actualmente activo incluyendo cosas como $wp_query->is_home y $wp_query->is_author, etc.

Después de que el enganche de filtro parse_query ejecute, WordPress llamará a get_posts() y cargará una lista de publicaciones según lo especificado en el $wp_query actualmente activo. Por lo tanto, parse_query es a menudo un gran lugar para que WordPress cambie de opinión acerca de qué publicaciones se van a cargar.

En su caso de uso, queremos que WordPress se filtre según las empresas seleccionadas; es decir, para mostrar solo aquellos listados que se han asociado con el negocio seleccionado (yo diría que "... solo aquellos listados que han sido" categorizados "por el negocio seleccionado" pero eso no es técnico correcto; category es su propia taxonomía con business, excepto que category está integrado en WordPress y business es personalizado. Pero para aquellos familiarizados con la categorización de publicaciones, esto puede ayudarlo a entender ya que funcionan de manera casi idéntica. .)

En el código. Lo primero que hacemos es capturar una referencia al $wp_query actualmente activo query_vars para que sea más conveniente trabajar con él, como lo hace dentro de la función parse_query() de WordPress. A diferencia de $wp_query->query, que se usa para reflejar los parámetros pasados ​​en la URL, la matriz $wp_query->query_vars se usa para controlar la consulta que ejecuta WordPress y se espera que se modifique. Entonces, si necesita modificar uno, ese sería el uno (al menos yo pensar que es el diferente entre los dos; si alguien sabe lo contrario por favor hágamelo saber para que pueda actualiza esto!)

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

A continuación, probamos $pagenow para asegurarnos de que estamos cargando WordPress desde la ruta URL /wp-admin/edit.php. Hacemos esto para evitar equivocaciones accidentales en otras páginas. También nos aseguramos de que tengamos tanto business como elemento taxonomy y también un elemento term. (Tenga en cuenta que taxonomy y term son un par; se usan juntos para permitir consultar un término de taxonomía; tengo que tener ambos o WordPress no sabe qué taxonomía inspeccionar).

Podría preguntarse cómo apareció business en el elemento taxonomy de la matriz query_vars. Lo que escribimos en nuestro gancho parse_query activó la magia interna de WordPress que se colocó en espera cuando registró la taxonomía "business" estableciendo que query_var sea verdadero (register_taxonomy() copia el nombre de la taxonomía como su query_var; por supuesto, puede cambiarlo. a menos que tenga un conflicto, es mejor seguir con el mismo):

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

Ahora, WordPress '$ wp_query fue escrito para usar slugs para consultas filtradas de taxonomía estándar, no ID de término de taxonomía. Para este caso de uso, lo que realmente necesitamos para que funcione nuestra consulta de filtrado son:

taxonomy: negocio

term: business-1 (es decir, la slug)

No estas

taxonomy: negocio

term: 27 (es decir, el term_id)

De manera interesante y desafortunadamente, el menú desplegable generado por wp_dropdown_categories() establece el <option> 's value en el término (/ business') term_id, not el término slug. Así que necesitamos convertir $wp_query->query_vars['term'] de un term_id numérico a su cadena slug como se indica en el fragmento de código desde arriba (Tenga en cuenta que esta no es la forma más eficaz de consultar una base de datos, pero hasta que WordPress agregue soporte para term_ids en su consulta, es lo mejor que podemos ¡hacer!):

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

¡Y eso es! Con esas dos funciones obtienes el filtrado que deseas.

PERO ESPERE, HAY MÁS! :-)

Seguí adelante y agregué una columna "Empresas" _ a tu lista de listado porque, bueno, sabía que iba a ser tu próxima pregunta. Sin tener una columna para lo que filtra puede ser muy confuso para el usuario final. (Yo también luché con eso, ¡y era el programador!) Por supuesto, ya puede ver la columna "Empresas" en las capturas de pantalla anteriores.

Paso # 3: El gancho del filtro manage_posts_columns.

Para agregar una columna a la lista de publicaciones, es necesario llamar a dos (2) enlaces adicionales. El primero es manage_posts_columns o la versión específica del tipo de publicación manage_listing_posts_columns que llamé en su lugar. Acepta un parámetro (posts_columns) y se llama desde /wp-admin/includes/template.php (en v3.0.1 esa llamada está en la línea 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;
}

Su función de enganche manage_posts_columns se pasa una matriz de columnas donde el valor es el encabezado de columna mostrado y la clave es el identificador interno de columna. Los identificadores de columna estándar pueden incluir estos y más: 'cb', 'title ', 'author', ``' date'`, etc.

'cb', es la columna checkbox y tanto 'title' como 'date' se refieren a post_title y post_date de la tabla wp_posts, respectivamente. 'author' por supuesto es el campo post_author después de que el nombre del autor se recupera de la tabla wp_users.

 Screenshot of the 'cb' posts column as a checkbox. 
(fuente: mikeschinkel.com )

Para el gancho manage_posts_columns, simplemente queremos insertar nuestra columna businesses en el arreglo $posts_columns antes de 'author', ¡asumiendo que algún otro complemento aún no haya eliminado author de la lista!

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

(Notacuando escribí add_businesses_column_to_listing_list() se me ocurrió que PHP debe tiene una manera más fácil de insertar un valor en una matriz asociativa en ¿El orden correcto?!? ¿O al menos tiene que haber una función en el núcleo de WordPress para hacerlo? Pero como Google me decepcionó, opté por lo que funcionó. Si alguien tiene alguna alternativa sugerida, estaré encantado de hacerlo. ¡avanzar!)

Lo que finalmente nos lleva a ...

Paso # 4: El gancho de acción manage_posts_custom_column

Lo segundo de los dos (2) que debemos hacer para que nuestros negocios se muestren en la columna es dar salida al nombre de cada uno de los negocios asociados utilizando el gancho de acción manage_posts_custom_column. Este enlace acepta dos (2) parámetros (column_id y post_id) y también se llama desde /wp-admin/includes/template.php (en v3.0.1 esa llamada está en la línea 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;
        }
    }
}

Este gancho se llama para cada columna para cada fila de publicación (/ negocio). Primero verificamos que estamos trabajando solo con el tipo de publicación personalizada listing y luego usamos una declaración switch para probar contra el column_id. Escogí switch porque este gancho a menudo se usa para generar resultados para muchas columnas diferentes, especialmente si usamos una función para muchos tipos de publicaciones diferentes que podrían tener este aspecto:

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

Al inspeccionar nuestro caso de uso un poco más cerca, verá la función get_the_terms() que simplemente devuelve la lista de términos para esta taxonomía (es decir, las empresas para este listado). Aquí obtenga el permalink para la página web de front-end del término que normalmente enumera las publicaciones que están asociadas con el término pero, por supuesto, podrían diferir dependiendo del tema y/o los complementos instalados.

Usamos el enlace permanente para enlazar el término solo porque me gusta enlazar cosas. Luego, combinamos todos los términos con hipervínculos (/ negocios) separados por el carácter de canalización ('|') y enviamos al búfer PHP que lo envía al navegador/cliente HTTP del usuario:

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

AHORAfinalmente hemos terminado.

Resumen

Entonces, en resumen, debe usar los siguientes cuatro (4) enlaces para obtener un filtro y una columna relacionada en la página de la lista de publicaciones personalizadas (Oh, también funcionará con las publicaciones y las páginas). Estas son:

  • Paso # 1: El gancho de acción restrict_manage_posts.
  • Paso # 2: El gancho del filtro parse_query.
  • Paso # 3: El gancho del filtro manage_posts_columns.
  • Paso # 4: El gancho de acción manage_posts_custom_column

Donde descargar el código

Pero si te obligara a leer todo lo anterior, entonces no sería una persona muy agradable si también te hiciera descifrar el código para poder probarlo. Pero al contrario de lo que dicen algunas personas, soy Niza. Así que aquí tienes

NOTA a @tarasm: Incluí ganchos para register_post_type() y register_taxonomy() para que otros puedan probar esto sin tener que recrearlos. Probablemente querrá eliminar esas dos llamadas de función antes de probar esto.

EL FIN


Respuesta original:

Hola @tarasm :

¿Está buscando un menú desplegable en la parte superior como esta pantalla o está buscando un menú desplegable por registro de publicación y si es así, cómo esperaría que funcionara este último?

 How to Create Sort By functionality for a Custom Post Type in the WordPress Admin 
(fuente: mikeschinkel.com )

Si es el primero, eche un vistazo a esta respuesta a la pregunta ¿Cómo ordenar el área de administración de un tipo de publicación personalizada de Wordpress por un campo personalizado? Si eso es lo que necesita, puedo proporcionar más detalles relacionados con la taxonomía.

138
MikeSchinkel

Solo quería compartir una implementación alternativa. No tenía el increíble tutorial de Mike cuando estaba pensando esto, así que mi solución es un poco diferente. Específicamente, voy a simplificar el paso # 1 y eliminar _ ​​paso # 2de Mike - los otros pasos siguen siendo aplicables.

En el tutorial de Mike, usar wp_dropdown_categories() nos ahorra algo de creación manual de listas, pero requiere una modificación de consulta condicional complicada (paso # 2) para manejar su uso de ID en lugar de slug. Sin mencionar la dificultad de modificar ese código para lidiar con otros escenarios, como los múltiples filtros de taxonomía.

Otro enfoque es simplemente no utilizar la wp_dropdown_categories() defectuosa en absoluto, sino en lugar de construir nuestras propias listas de selección desplegables desde cero. No es tan complicado, toma menos de 30 líneas de código, y no requiere enganchar parse_query en absoluto:

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

Simplemente conectando las taxonomías deseadas en la matriz $filters, puede generar rápidamente múltiples filtros de taxonomía. Aparecen exactamente iguales a los de las capturas de pantalla de Mike. Luego puede seguir con paso # 3 y # 4.

44
somatic

Aquí hay una versión de esto que crea y aplica automáticamente filtros de todas las taxonomías que se aplican a todos los tipos de publicaciones personalizadas que los usan. (qué bocado) De todos modos, también lo modifiqué para que funcione con wp_dropdown_categories () y wordpress 3.1. El proyecto en el que estoy trabajando se llama ToDo, puede cambiar el nombre de las funciones a algo que tenga sentido para usted, pero esto debería funcionar para todo de forma automática.

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

Tenga en cuenta que estoy usando un complemento que agrega 'term_order' como una forma de ordenar términos, tendrá que cambiar eso o eliminar ese argumento para volver al valor predeterminado.

13
Drew Gourley

Respuesta tardía

Editar

He escrito Filterama , un complemento que agregará esta funcionalidad de la manera más fácil posible.

Actualización para WordPress 3.5+

Ahora que las cosas son mucho más fáciles, aquí hay una muy solución simple como plugin o mu-plugin.

Utiliza la menor cantidad de recursos posible, se carga solo en las pantallas necesarias y agrega Columnas + Filtros para cada taxonomía 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,
            ) );
        }

    }

}

Y luego solo necesitas una clase personalizada de Walker.

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

Solo quería hacer una nota rápida. En las versiones más recientes de WP, las listas de publicaciones en admin son manejadas por la clase WP_Posts_List_Table. El código de apply_filters es ahora como sigue:

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

Entonces, para agregar nuevas columnas, un gancho add_filter debería ser así:

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

Aquí va un ejemplo:

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

Ahora, para las filas de post. Este es el código que maneja los datos de columna en los listados:

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 los datos de nuestras publicaciones, debemos agregar un gancho de acción como este:

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

Ejemplo (este ejemplo usa taxonomías, pero puedes consultar cualquier otra cosa):

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

    default:
      break;
  }
}
7
mines

TRABAJA EN WP 3.2!

custom_post_type: books custom_taxonomy: genre

Solo modifique donde dice: // cambie 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');
7
lacroixca

Supongo que esto no es muy conocido, pero a partir de wordpress 3.5, puede pasar 'show_admin_column' => true a register_taxonomy. Esto hace 2 cosas:

  1. Agrega la columna de taxonomía a la vista de lista de tipo de publicación de administrador
  2. Al hacer clic en el nombre del término en la columna de taxonomía, de hecho, filtrará la lista a ese término .

Entonces, no es exactamente lo mismo que tener una selección, sino casi la misma funcionalidad, ancho solo una fila de código.

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

Además, como puede leer, hay un nuevo filtro adaptado para la columna de taxonomía de adición manual (si realmente lo necesita).

2
Luca Reghellin

Aquí hay una manera de hacerlo usando la acción restrict_manage_posts. Parece funcionar bien para mí y agrega la capacidad de filtrar por taxonomía para todos los tipos de publicaciones y las taxonomías 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";
        }
} 

Una nota: intenté restringir la profundidad porque algunas de mis taxonomías jerárquicas son bastante grandes pero no funcionó. ¿Podría haber un error en la función wp_dropdown_categories?

2
Brad Trivers

Versión jerárquica de la respuesta de @ somatic, según lo 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);
    }

}
?>

Básicamente eliminé el código que creó las opciones y lo puse en su propia función. La función 'generate_taxonomy_options', además de tomar tax_slug, también toma un parámetro de nivel y padre. La función asume que sus opciones de creación para el padre 0, que seleccionarán todos los términos de nivel raíz. En el bucle, la función se llamará a sí misma de forma recursiva, utilizando ese término actual como padre e incrementando el nivel en uno. Automáticamente agrega garrapatas al lado a medida que avanzas por el árbol y listo!

1
Manny Fleurmond

Actualización de la respuesta de @Drew Gourley para WP 3.3.1 (e incorporando código de http://wordpress.org/support/topic/wp_dropdown_categories-generating-url-id-number-instead-of- slug? respuestas = 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";
    }
}
1
rinogo

Solo probé ambos códigos, de Mike y somatic, y me preguntaba cómo obtener una cosa de cada técnica:

Con el código de Mike, se muestra la lista desplegable con la opción hierarchical , que ayuda mucho. Pero para mostrar dos menús desplegables tuve que duplicar la instrucción if ($typenow=='produtos') {...} en la función restrict_listings_by_business() y también el if ($pagenow=='edit.php' && ... } en la función convert_business_id_to_taxonomy_term_in_query($query) que ahora da mucho código.

Con el código de somatic solo necesito especificar las taxonomías que me gustaría ver, ya que las listas desplegables y bam funcionan; $filters = array('taxo1', 'taxo2');

Pregunta: ¿Puedo obtener un enfoque somático y también tener la opción jerárquica ?

Muchas gracias de todos modos por este tutorial, me ayudó mucho!

0
kevin

Disculpas por el hecho de que, como nuevo usuario, no puedo publicar comentarios, pero puedo publicar una respuesta ...

A partir de WordPress 3.1 (RC 1) la respuesta de Mike (que me ha servido tan bien durante los últimos dos meses) ya no funciona para mí; La restricción por cualquier taxonomía infantil da un resultado vacío. Intenté la actualización de Somatic y funcionó muy bien; aún mejor, funciona con consultas de taxonomía múltiples que se ha trabajado en esta versión.

0
rsigg

El tutorial de Mike sobre esto es genial! Probablemente no me hubiera molestado en agregar esta funcionalidad a mi complemento de Categorías de Medios si hubiera tenido que resolverlo por mi cuenta.

Dicho esto, creo que usar parse_query y luego obtener la consulta para el término no es necesario. Es más limpio para crear tu propia clase de caminante personalizado. Tal vez eso no fue posible cuando escribió su publicación: tiene 3 años cuando escribí esto.

Echa un vistazo a este gran fragmento de github. Funciona como un encanto, cambia los ID en los valores desplegables en slugs, por lo que funciona de forma nativa sin modificar la consulta.

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

0
eddiemoya