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


129

He creado un Tipo de publicación personalizado llamado 'listing'y agregué una Taxonomía personalizada llamada 'businesses'. Me gustaría agregar una lista desplegable de empresas a la lista de administradores para los listados.

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

Categorías desplegables en publicaciones

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 empresas a la lista de administradores para los listados?


8
Gracias por la captura de pantalla, realmente ayuda tenerlos.
MikeSchinkel

Hay un complemento Admin Taxonomy Filter que puede hacer el trabajo exacto.
Anh Tran

Respuestas:


140

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:

... veamos algunas capturas de pantalla para el producto terminado:

Lista de la página de lista sin filtro:

Lista de la página de lista sin filtro
(fuente: mikeschinkel.com )

Página de lista de listados con filtrado:

Página de lista de listados con filtrado
(fuente: mikeschinkel.com )

El código

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

Paso # 1: El restrict_manage_postsgancho de acción.

Lo primero que debe hacer es conectar la restrict_manage_postsacción 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 adecuada sobre la lista de Listado de publicaciones.

<?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 comprobando la $typenowvariable para asegurarnos de que estamos en una post_typede 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 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 haber codificado, pero eso no es muy bueno si necesita internacionalizar más tarde.) Luego llamamos wp_dropdown_categories()con todos los argumentos apropiados en la $argsmatriz para generar el 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? Miremos 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, será "Mostrar todos los negocios ", pero podríamos haberlo llamado "Listados para todos los negocios" o lo que quiera.

  • taxonomy- Este argumento le dice a la función de qué taxonomía extraer los términos aunque la función tenga categoriessu nombre. En v2.8 y versiones 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 usará para el nameatributo del elemento <select> generado para el menú desplegable. En caso de que no sea obvio, este también es 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 ordenar comprar los nametérminos de la taxonomía, es decir, los nombres comerciales en este caso.

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

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

  • depth- Este argumento colabora con el hierarchicalargumento para determinar cuántos niveles de profundidad debería ir la función al mostrar elementos secundarios.

  • show_count- Si trueeste argumento mostrará un recuento de publicaciones entre paréntesis a la izquierda del nombre del término dentro del menú desplegable. En este caso, 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 no están asociados con una publicación (es decir, empresas que no están asociadas con una lista), al configurar esto, truese omitirá su inclusión en el menú desplegable.

La lista desplegable de taxonomía debe contar con jerarquía y conteo
(fuente: mikeschinkel.com )

Paso # 2: El parse_querygancho del filtro.

A continuación llamamos nuestras atenciones al enlace de parse_queryfiltro 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 activo $wp_queryincluyendo cosas como $wp_query->is_homey $wp_query->is_author, etc.

Después de que se parse_queryejecute el enlace de filtro, WordPress llamará get_posts()y cargará una lista de publicaciones en función de lo que se especifica en el activo actual $wp_query. Por parse_querylo tanto, a menudo es un gran lugar para hacer que WordPress cambie de opinión sobre qué publicaciones va a cargar.

En su caso de uso, queremos que WordPress filtre según las empresas seleccionadas; es decir, para mostrar solo los listados que se han asociado con el negocio seleccionado (yo diría "... solo aquellos listados que han sido " categorizados " por el negocio seleccionado" pero eso no es técnico correcto; categoryes su propia taxonomía en pares con businessla excepción de que categoryse construye en WordPress y businesses personalizado. Pero para aquellos familiarizados con la categorización de mensajes que esto puede ayudar a entender a medida que trabajan de manera casi idéntica. Pero estoy divagando ...)

En el código. Lo primero que hacemos es tomar una referencia a los actualmente activos $wp_query's query_varspara que sea más conveniente para trabajar, al igual que como se hace dentro de WordPress propia parse_query()función. A diferencia de lo $wp_query->queryque se usa para reflejar los parámetros pasados ​​en la URL, la $wp_query->query_varsmatriz se usa para controlar la consulta que ejecuta WordPress y se espera que se modifique. Entonces, si necesita modificar uno, ese sería el indicado (al menos creo que es la diferencia entre los dos; si alguien sabe lo contrario , ¡ hágamelo saber para que pueda actualizar 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 $pagenowpara asegurarnos de que realmente estamos cargando WordPress desde la ruta URL /wp-admin/edit.php. Hacemos esto para evitar arruinar accidentalmente consultas en otras páginas. También verificamos para asegurarnos de que tenemos tanto businessun taxonomyelemento como un termelemento también. (Tenga en cuenta taxonomyy termson un par; se usan juntos para permitir la consulta de un término de taxonomía; debe tener ambos o WordPress no sabe qué taxonomía inspeccionar).

Quizás se pregunte cómo businessapareció el taxonomyelemento de la query_varsmatriz. Lo que escribimos en nuestro parse_queryanzuelo activó la magia interna de WordPress que se puso a la espera cuando registró la " business" taxonomía estableciéndola query_varcomo verdadera ( register_taxonomy()copia el nombre de la taxonomía como tal query_var; puede cambiarla, por supuesto, pero a menos que tenga un conflicto es mejor seguir con lo 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, $ wp_query de WordPress se escribió 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 nuestra consulta de filtrado funcione son estos:

taxonomy: negocios

term: negocio-1 (es decir, el slug)

No estos:

taxonomy: negocios

term: 27 (es decir, el term_id)

Curiosamente y desafortunadamente, el menú desplegable generado al wp_dropdown_categories()establecer el atributo <option>'s valuepara el término (/ negocio') term_id, no el término slug. Por lo tanto, debemos convertir $wp_query->query_vars['term']de una term_idcadena numérica a su cadena de la slugsiguiente manera en el fragmento enganchado desde arriba (¡Tenga en cuenta que esta no es la forma más eficiente 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 ESPERA HAY MAS! :-)

Seguí adelante y agregué una columna de "Negocios" a su lista de Listado porque, bueno, sabía que iba a ser su próxima pregunta. Sin tener una columna para lo que filtra, puede ser muy confuso para el usuario final. (¡Luché con eso yo mismo y fui el programador!) Por supuesto, ya puedes ver la columna "Negocios" en las capturas de pantalla anteriores.

Paso 3: el manage_posts_columnsgancho del filtro.

Para agregar una columna a la lista de publicaciones, se requieren dos (2) ganchos más. El primero es manage_posts_columnsla versión específica del tipo de publicación manage_listing_posts_columnsque 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 manage_posts_columnsfunción de enlace pasa una matriz de columnas donde el valor es el encabezado de columna mostrado y la clave es el identificador de columna interno. Identificadores de columna estándar pueden incluir éstos y más: 'cb', 'title' 'author'``' date'`, etc.

'cb', es la checkboxcolumna y ambas 'title'y se 'date'refieren a post_titley post_datedesde la wp_poststabla, respectivamente. 'author'por supuesto, es el post_authorcampo después de recuperar el nombre del autor de la wp_userstabla.

Captura de pantalla de la columna de publicaciones 'cb' como una casilla de verificación.
(fuente: mikeschinkel.com )

Para el manage_posts_columnsgancho, simplemente queremos insertar nuestra columna businessesen la $posts_columnsmatriz antes 'author', ¡suponiendo que algún otro complemento aún no se haya eliminado authorde la lista!

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

( Tenga en cuenta que cuando escribí add_businesses_column_to_listing_list()se me ocurrió que PHP debe tener una forma más fácil de insertar un valor en una matriz asociativa en el orden correcto. ¿O al menos debe haber una función en el núcleo de WordPress para hacerlo? Pero desde Google me decepcionó, así que seguí con lo que funcionó. ¡Si alguien tiene alguna alternativa sugerida, estaré atento y agradecido de antemano!)

Lo que finalmente nos lleva a ...

Paso # 4: el manage_posts_custom_columngancho de acción

La segunda cosa de dos (2) que debemos hacer para que nuestras empresas se muestren en la columna es realmente mostrar el nombre de cada una de las empresas asociadas utilizando el manage_posts_custom_columngancho de acción. Este enlace acepta dos (2) parámetros ( column_idy post_id) y también se llama desde /wp-admin/includes/template.php(en v3.0.1 que la 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;
        }
    }
}

Se llama a este gancho para cada columna para cada fila de publicación (/ negocio). Primero verificamos que realmente estamos trabajando solo con el listingtipo de publicación personalizada y luego usamos una switchdeclaración para probar el column_id. Elegí switchporque 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 verse así:

<?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 get_the_terms()función que simplemente devuelve la lista de términos para esta taxonomía (es decir, empresas para este listado). Aquí obtenga el enlace permanente para la página web front-end del término que normalmente enumera las publicaciones asociadas con el término, pero, por supuesto, podría variar de acuerdo con el tema o los complementos instalados.

Usamos el enlace permanente para hacer un hipervínculo del término solo porque me gusta hacer hipervínculos de cosas. Luego fusionamos todos los términos con hipervínculos (/ empresas) juntos separados con el carácter de canalización (' |') y los 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);
}

AHORA finalmente hemos terminado.

Resumen

En resumen, debe usar los siguientes cuatro (4) ganchos para obtener un filtro y una columna relacionada en la página de lista de publicaciones personalizadas (Oh, también funcionará con Publicaciones y Páginas). Son:

  • Paso # 1: El restrict_manage_postsgancho de acción.
  • Paso # 2: El parse_querygancho del filtro.
  • Paso 3: el manage_posts_columnsgancho del filtro.
  • Paso # 4: el manage_posts_custom_columngancho de acción

Dónde descargar el código

Pero si te obligara a leer todo lo anterior, ¡ciertamente no sería una buena persona si también te obligara a desenterrar el código solo para poder probarlo! Pero al contrario de lo que dicen algunas personas, soy amable. Así que aquí tienes:

NOTA para @tarasm : incluí ganchos para aregister_post_type()yregister_taxonomy()para que otros pudieran probar esto sin tener que recrearlos. Probablemente desee 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, de ser así, cómo esperaría que este último funcione?

Cómo crear la funcionalidad Ordenar por para un tipo de publicación personalizada en el administrador de WordPress
(fuente: mikeschinkel.com )

Si es lo 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 proporcionarle más detalles relacionados con la taxonomía.


Estoy buscando 1 menú desplegable en la parte superior que muestre el filtro Categorías. Estaba deambulando si hay una forma estándar de hacer esto sin tener que escribir código personalizado.
Taras Mankovski

A primera vista, no creo que se pueda hacer sin código personalizado, pero luego no creo que el código personalizado sea significativo. Tengo una llamada de cliente para prepararme, así que tendrá que ser más tarde hoy.
MikeSchinkel

2
En realidad, ambas soluciones (somática y MikeSchinkel) no funcionan cuando intenta filtrar 2 taxonomías diferentes en el mismo filtro: - / Siempre filtra la última taxonomía cuando intenta filtrar 2+ al mismo tiempo.
Ünsal Korkmaz

1
@ Ünsal La versión actual de WordPress (3.0) no admite múltiples consultas de taxonomía, pero por lo que he escuchado, eso cambiará con la versión 3.1. Para que este ejemplo funcione con múltiples taxonomías, tendría que agregar algunas combinaciones y ubicaciones a la consulta a través de los ganchos de filtro Posts_join y posts_where.
Manny Fleurmond el

1
En WP 3.1+, los pasos uno y dos son mejores en la respuesta @ drew-gourley (en realidad, su paso 2 no funcionó para mí, creo que hay cambios en este filtrado en el nuevo WordPress).
Tomasz Struczyński

44

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

En el tutorial de Mike, el uso 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 múltiples filtros de taxonomía.

Otro enfoque es simplemente no utilizar los defectos wp_dropdown_categories(), sino crear 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 enganche parse_queryen 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 $filtersmatriz, puede generar rápidamente múltiples filtros de taxonomía. Parecen exactamente iguales a los de las capturas de pantalla de Mike. Luego puede continuar con los pasos 3 y 4 .


44
@somatic - ¡Buena actualización! Sí, usar wp_dropdown_categories()requiere muchas soluciones alternativas. Intento seguir con las funciones principales cuando es posible, pero como señalas a veces se necesita más trabajo de esa manera. Simplemente demuestra que con WordPress a menudo hay más de una buena forma de resolver un problema. ¡Buen trabajo!
MikeSchinkel

Acabo de dejar de trabajar para mí en WordPress 3.1. Tratando de averiguar qué cambió exactamente. Parece que todavía debería funcionar: la taxonomía y las babosas de término se muestran como valores GET en la URL, pero todo lo que resulta es 0 resultados
Manny Fleurmond

He estado tratando de hacer que esto funcione, pero la única forma en que pude fue usar el gancho parse_query, verificar la var de consulta de la taxonomía y establecer las variables de consulta de taxonomía y término en función de eso. Usando WP 3.1. ¿Deberían aparecer taxonomía y término en la URL cuando se envíe el filtro?
sanchothefat

2
¡Funciona como un encanto para mí! Solución muy elegante de hecho. Te debo una cerveza :)
Michal Mau

@somatic Esto funciona muy bien, pero ¿hay alguna manera de que $ term-> count solo cuente los términos para ese tipo de publicación? Por ejemplo, si tengo una taxonomía personalizada tanto para las fotos como para los videos, me mostrará al mirar la publicación personalizada de videos escribir el número total de publicaciones para ese término de ambos tipos de publicaciones personalizadas en lugar de solo el número total de publicaciones de videos que usan ese término.
Greenhoe

13

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 automáticamente.

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 los términos, tendrá que cambiar eso o eliminar ese argumento para volver al valor predeterminado.


muy sexy por cierto. Estaba recibiendo avisos de error, así que cambié if (isset ($ var)) a if (isset ($ var) && $ var> 0) para evitar tratar de encontrar términos asociados con el valor 0 de Ver todos. ah, y tuve que devolver $ query en la función
todo_convert_restrict

11

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 solución muy 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 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})"
                : ''
        );
    }
}

Le di un giro, pero parece que falta el método get_select ().
Dave Romsey

@ goto10 Tenías razón. Actualizado. Por cierto: es más fácil simplemente tomar el complemento vinculado. Estará disponible en el repositorio de complementos en una o dos semanas. (Ya confirmado).
Kaiser

Tuve que usar $this->setup_vars();al principio de public function setup()para tener "manage_taxonomies_for_{$this->post_type}_columns"trabajo
Christian

Pero podría ser porque lo uso en una función Theme.php conadd_action( 'init', array( 'WCM_Admin_PT_List_Tax_Filter', 'init' ) );
Christian

@ Christian Esto no es material de tema. Esto pertenece a un complemento y, como el código anterior, actualmente se carga mucho antes de que se carguen los Temas.
kaiser

7

Solo quería hacer una nota rápida. En las versiones más recientes de WP, la clase WP_Posts_List_Table maneja los listados de publicaciones en admin. El código apply_filters ahora es el siguiente:

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 publicaciones. 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 nuestros datos de 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 puede 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

¡FUNCIONA EN WP 3.2!

custom_post_type: books custom_taxonomy: género

Solo modifique donde dice: // cambie AQUÍ

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

Esa es una solución agradable y fácil para WP 3.2+.
petermolnar

funciona pero __("Show All {$info_taxonomy->label}")es una forma incorrecta de usar cadenas traducibles.
Mark Kaplun

2

Aquí hay una manera de hacerlo usando la acción restrict_manage_posts. Parece que funciona bien para mí y agrega la capacidad de filtrar por taxonomía para todos los tipos de publicaciones y 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 ser un error en la función wp_dropdown_categories?


2

Supongo que esto no se sabe bien, pero a partir de wordpress 3.5, puede pasar 'show_admin_column' => truea 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, pero 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 diseñado para agregar manualmente la columna de taxonomía (si realmente lo necesita).


1

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 primario y de nivel. La función supone que está creando opciones para el padre 0, que seleccionará todos los términos del nivel raíz. En el bucle, la función se llamará recursivamente a sí misma, utilizando ese término actual como padre y aumentando el nivel en uno. ¡Agrega garrapatas automáticamente a un lado cuanto más profundo bajes del árbol y listo!


1

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

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 meses) ya no me funciona; restringir por cualquier taxonomía hijo da un resultado vacío. Probé la actualización de Somatic y funcionó muy bien; aún mejor, funciona con múltiples consultas de taxonomía que se han trabajado en esta versión.


Por alguna razón, la versión de
somatic

0

Acabo de probar 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, muestra la lista desplegable con la opción jerárquica , lo que ayuda mucho. Pero para mostrar dos menús desplegables tuve que duplicar la if ($typenow=='produtos') {...}declaración en la función restrict_listings_by_business()y también if ($pagenow=='edit.php' && ... }en la convert_business_id_to_taxonomy_term_in_query($query)función que ahora da mucho código.

Con el código somático solo necesito especificar las taxonomías que me gustaría ver como desplegables y bam, funciona; $filters = array('taxo1', 'taxo2');

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

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


Se mi respuesta para una solución jerárquica
Manny Fleurmond

0

¡El tutorial de Mike sobre esto es genial! Probablemente no me habría 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_queryy luego obtener la consulta del término no es necesario. Es más limpio para crear tu propia clase de andador personalizado. Tal vez eso no fue posible cuando escribió su publicación: tenía 3 años cuando escribí esto.

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

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