将分类过滤器添加到自定义帖子类型的管理员列表中?


129

我创建了一个名为的自定义帖子类型,'listing'并添加了一个名为的自定义分类法'businesses'。我想将商家的下拉列表添加到列表的管理员列表中。

这是此功能在帖子管理列表中的外观(我希望对“自定义帖子类型”也是如此):

帖子中的类别下拉列表

这是我当前的代码这与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();
}

如何将商家的下拉列表添加到列表的管理员列表中?


8
感谢您提供的屏幕截图,拥有它们确实有帮助。
MikeSchinkel 2010年

有一个插件Admin Taxonomy Filter可以完成确切的工作。
Anh Tran

Answers:


140

更新:我已经添加了一个完整的新答案,但是即使如此,我也将我的原始回复留在了底部,前几条评论引用了该答案。


@tarasm

尽管我说这不难,但还是有些涉及。但是在深入研究代码之前...

屏幕截图:

...让我们检查一下成品的屏幕截图:

没有过滤的列表列表页面:

列表列表页面,无过滤
(来源:mikeschinkel.com

具有过滤功能的列表列表页面:

带有过滤功能的列表列表页面
(来源:mikeschinkel.com

编码

所以我们开始...(注意:我使用了单数形式的分类法名称business;希望能与您匹配。从过去在WordPress和数据库开发方面的大量经验中,我相信最好采用这种方式)

步骤1:restrict_manage_posts动作挂钩。

您需要做的第一件事是挂接restrict_manage_posts没有参数且从中调用的操作/wp-admin/edit.php(在v3.0.1中,该调用位于第378行。)这将允许您在列表上方的适当位置生成下拉选择。列出帖子。

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

我们首先检查$typenow变量,以确保我们实际上位于post_typelisting。如果您不这样做,那么您会在所有情况下都需要此下拉列表,在某些情况下是您想要的,但在这种情况下不是。

接下来,我们使用加载有关业务分类的信息get_taxonomy()。我们需要它来检索分类法的标签(即“ Businesses ”;我们可以进行硬编码,但是如果您以后需要进行国际化,那就不好了。)然后我们调用数组wp_dropdown_categories()中的所有适当参数$args来生成落下

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

但是适当的论点是什么?让我们分别查看每个:

  • show_optional_all-非常简单明了,它是首先显示在下拉菜单中的内容,并且没有应用过滤。在我们的情况下,它是“显示所有业务 ”,但我们可以将其称为“所有业务列表”或任何您喜欢的名称。

  • taxonomy-此参数告诉函数从categories名称中提取什么分类法,即使该函数具有其名称。在v2.8和更早版本中,WordPress没有自定义分类法,但是当他们添加时,团队决定将一个分类法参数添加到此函数比创建另一个具有另一个名称的函数要容易得多。

  • name-此参数允许您指定WordPress name用于下拉菜单所生成的<select>元素的属性的值。以防万一,这也是在过滤时将在URL中使用的值。

  • orderby-此参数告诉WordPress如何按字母顺序排列结果。在我们的案例中,我们指定要订购购买name分类法中的术语,即本例中的公司名称。

  • selected-需要此参数,以便下拉菜单可以显示下拉菜单中的当前过滤器。它应该是term_id所选分类术语中的。在我们的情况下,它可能term_id来自“业务2”。我们从哪里得到这个价值?来自WordPress的全局变量$wp_query; 它具有一个query包含所有URL参数及其值的数组的属性(当然,除非已经有一些任性的插件对其进行了修改。)鉴于WordPress处理方式,term当用户单击过滤器时,URL 上将传递URL参数如果用户选择了有效期限(即列出的商家之一),则按钮。

  • hierarchical-通过将其设置为该值,true您可以告诉函数尊重分类法的层次结构性质,并在术语(企业)实际上有子级时以树状视图显示它们。有关查看效果的屏幕截图,请参见下文。

  • depth-此参数与该参数协作hierarchical以确定该功能在显示子级时应深入多少层。

  • show_count-如果true此参数将显示计数,则在下拉菜单中术语名称左侧的括号内。在这种情况下,它将显示与企业关联的列表的数量。有关查看效果的屏幕截图,请参见下文。

  • hide_empty-最后,如果有分类中的那些条款与帖子相关联(即企业不与上市相关的),那么设置这true会忽略它们被包含在下拉。

分类下拉列表应具有层次结构并计数
(来源:mikeschinkel.com

步骤2:parse_query过滤器挂钩。

接下来,我们将注意力转移到parse_query具有一个参数($query)并从中调用的筛选器挂钩/wp-includes/query.php(在v3.0.1中,该调用位于第1549行。)当WordPress完成检查URL并在当前目录中设置所有适当的值时调用活跃的,$wp_query例如$wp_query->is_home$wp_query->is_author等。

在经过parse_query过滤钩子运行WordPress会调用get_posts()并加载了基于什么是在当前活动的指定职位名单$wp_query。因此parse_query,通常使WordPress改变想法的地方是它要加载哪些帖子。

在您的用例中,我们希望让WordPress根据所选业务进行过滤;即仅显示与所选业务相关联的那些列表(我会说“ ...仅由所选业务“ 分类”的那些列表”,但这在技术上不正确;category这是对等方自己的分类法吗?business不同之处在于category内置到WordPress和business是定制的。但是,对于那些熟悉的职位分类,这可能会帮助你了解他们的工作几乎相同。但是,我离题...)

转到代码。我们首先要做的是抓住当前激活的一个参考$wp_queryquery_vars,以便它一起工作更方便,就像它的WordPress中如何实现自己的parse_query()功能。与$wp_query->query用于镜像在URL上传递的参数的方法不同,该$wp_query->query_vars数组用于控制WordPress运行的查询并有望对其进行修改。因此,如果您需要修改一个,那就是那个(至少我认为这是两者之间的区别;如果有人知道,让我知道,以便我进行更新!)

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

接下来,我们进行测试$pagenow以确保确实从URL路径加载了WordPress /wp-admin/edit.php。我们这样做是为了避免意外搞乱其他页面上的查询。我们还检查以确保我们同时business具有taxonomy元素和term元素。(请注意,taxonomy并且term是一对;它们一起使用以允许查询一个分类法术语;必须同时使用这两个方法,否则WordPress不知道要检查哪个分类法。)

您可能想知道如何在数组businesstaxonomy元素中出现query_vars。我们在parse_query钩子中写的内容触发了WordPress的内部魔力,当您business通过将其设置query_var为true来注册分类法时,便会等待(register_taxonomy()复制分类法的名称为该分类法query_var;您当然可以更改它,但除非有冲突,否则将被保留)最好坚持一样):

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

现在,WordPress的$ wp_query编写为针对标准分类法过滤查询使用子词,而不是分类法术语ID。对于此用例,我们真正需要进行过滤查询的是:

taxonomy业务

term业务1 (即slug

不是这些:

taxonomy业务

term27(即term_id

有趣的是,不幸的是所产生的下拉wp_dropdown_categories()设置<option>value属性术语的(/业务“) term_id没有期限slug。因此,我们需要从上面截取的代码段中将$wp_query->query_vars['term']数字从数字转换term_id为它的字符串slug(请注意,这不是查询数据库的最有效方法,但是直到WordPress在其查询中添加对term_ids的支持之前,这是我们能做到的最好的方法!) :

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

就是这样!使用这两个功能,您可以获得所需的过滤。

但是,还有更多!:-)

我继续在您的清单列表中添加了“企业”列,因为,我知道这将是您的下一个问题。如果没有针对您要过滤的内容的列,最终用户可能会感到非常困惑。(我自己为此苦苦挣扎,而我是编码员!)您当然可以在上面的上一幅屏幕快照中看到“ Businesses”一栏。

步骤#3:manage_posts_columns过滤器挂钩。

要在发布列表中添加一列,需要调用另外两个(2)挂钩。第一个是我调用manage_posts_columns的特定于帖子类型的版本manage_listing_posts_columns。它接受一个参数(posts_columns)并从中/wp-admin/includes/template.php调用(在v3.0.1中,该调用位于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;
}

您的manage_posts_columns钩子函数将传递一个列数组,其中值是显示的列标题,键是内部列标识符。标准列标识符可以包括以下内容以及更多内容:'cb''title“,” 'author',“日期”等。

'cb',是checkbox柱和两个'title''date'post_titlepost_datewp_posts表中,分别。'author'当然是post_authorwp_users表中检索作者姓名之后的字段。

“ cb”帖子列的屏幕截图作为一个复选框。
(来源:mikeschinkel.com

对于manage_posts_columns挂钩,我们只是想将我们的列 businesses插入到$posts_columns数组中'author',假设author尚未从列表中删除其他插件!

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

请注意,在我写这篇文章add_businesses_column_to_listing_list()时,我发现PHP 必须有一种更简便的方法来按正确的顺序将值插入到关联数组中!让我失望,让我继续努力。如果有人有任何建议的替代方案,我会不胜感激并提前感谢!)

终于把我们带到了...

步骤#4:manage_posts_custom_column动作挂钩

我们需要做的两(2)件事的第二件事是使我们的企业显示在该列中,这实际上是使用manage_posts_custom_column操作钩子实际输出每个关联企业的名称 。该钩子接受两(2)个参数(column_idpost_id),并且也从/wp-admin/includes/template.php(在第1459行中的调用在v3.0.1中)被调用:

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

每个post(/ business)行的每一列都会调用此钩子。我们首先验证我们确实只在使用listing自定义帖子类型,然后使用switch语句对进行测试column_id。我之所以选择switch它,是因为该钩子通常用于为许多不同的列生成输出,尤其是当我们对多种不同的帖子类型使用一个函数时,它看起来可能像这样:

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

再仔细检查一下我们的用例,您会看到该get_the_terms()函数仅返回此分类法的术语列表(即该列表的企业)。这里获得该术语的前端网页的永久链接,该网页通常列出相关的帖子这个词,但根据安装的主题和/或插件,可能会有所不同。

我们使用永久链接对术语进行超链接只是因为我喜欢对事物进行超链接。然后,我们将所有超链接的术语(/ business)合并在一起,并用竖线(' |')分隔,并输出到PHP缓冲区,该缓冲区将其发送到用户的浏览器/ HTTP客户端:

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

现在我们终于完成了。

摘要

因此,总而言之,您需要使用以下四(4)个钩子来获取自定义帖子列表页面中的过滤器和相关列(哦,它也可以用于帖子和页面。)它们是:

  • 步骤1:restrict_manage_posts动作挂钩。
  • 步骤2:parse_query过滤器挂钩。
  • 步骤#3:manage_posts_columns过滤器挂钩。
  • 步骤#4:manage_posts_custom_column动作挂钩

在哪里下载代码

但是,如果我强迫您通读以上所有内容,那么如果我也让您挖掘出代码以尝试一下,那我肯定不是一个好人!但是与某些人所说的相反,我很好。所以,你去:

@tarasm的注意事项:我为register_post_type()和包含了钩子,register_taxonomy()以便其他人可以尝试这样做而不必重新创建它们。在测试之前,您可能希望删除这两个函数调用。

结束


原始回复:

@tarasm

您是此屏幕顶部寻找一个下拉列表,还是在每个帖子记录中寻找一个下拉列表,如果是的话,您希望后者如何工作?

如何在WordPress管理员中为自定义帖子类型创建“排序依据”功能
(来源:mikeschinkel.com

如果是前者,请看此问题的答案,该问题如何按自定义字段对Wordpress自定义帖子类型的管理区域进行排序? 如果需要,我可以提供与分类法有关的更多详细信息。


我正在顶部显示1个下拉列表,该下拉列表将显示“类别”过滤器。如果有一种无需编写自定义代码的标准方法,我就会四处徘徊。
塔拉斯·曼科夫斯基

乍一看,我认为您无法执行自定义代码,但后来我认为自定义代码并不重要。我有一个客户电话来做准备,所以虽然要在今天晚些时候进行。
MikeSchinkel 2010年

2
实际上,当您尝试在同一过滤器中过滤2种不同的分类法时,两种解决方案(somatic和MikeSchinkel)均不起作用:-/在尝试同时过滤2+时始终过滤最新的分类法。
Ünsal科尔克马兹

1
@Ünsal当前版本的WordPress(3.0)不支持多个分类法查询,但据我所知,这将在3.1版中发生变化。为了使该示例适用于多种分类法,您必须通过Posts_join和posts_where过滤器挂钩向查询中添加一些联接和位置。
Manny Fleurmond 2011年

1
在WP 3.1+中,@ drew-gourley答案中的第一步和第二步更好(实际上,您的第2步对我不起作用,我认为新WordPress中的此过滤有所更改)。
TomaszStruczyński2011年

44

只是想共享一个替代实现。当我弄清楚这一点时,我没有Mike的精彩教程,因此我的解决方案有所不同。具体来说,我将简化Mike的步骤1,取消 步骤2-其他步骤仍然适用。

在Mike的教程中,使用为wp_dropdown_categories()我们节省了一些手动的列表构建,但是需要进行一些复杂的条件查询修改(步骤2)来处理ID的使用,而不是处理。更不用说修改该代码以处理其他情况(例如多个分类法过滤器)的困难。

另一种方法是根本不使用有缺陷wp_dropdown_categories()的东西,而是从头开始构建我们自己的下拉选择列表。它不是那么复杂,只需要少于30行代码,根本不需要钩子parse_query

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

    // only display these taxonomy filters on desired custom post_type listings
    global $typenow;
    if ($typenow == 'photos' || $typenow == 'videos') {

        // create an array of taxonomy slugs you want to filter by - if you want to retrieve all taxonomies, could use get_taxonomies() to build the list
        $filters = array('plants', 'animals', 'insects');

        foreach ($filters as $tax_slug) {
            // retrieve the taxonomy object
            $tax_obj = get_taxonomy($tax_slug);
            $tax_name = $tax_obj->labels->name;
            // retrieve array of term objects per taxonomy
            $terms = get_terms($tax_slug);

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

通过简单地将所需的分类法插入到$filters阵列中,您可以快速输出多个分类法过滤器。它们看起来与Mike的屏幕截图完全相同。然后,您可以执行步骤#3#4


4
@somatic-不错的更新!是的,使用wp_dropdown_categories()确实需要很多解决方法。我会尽可能地坚持使用核心功能,但是正如您指出的那样,有时这样做需要做更多的工作。只是为了证明使用WordPress通常可以解决问题的方法不止一种。做得好!
MikeSchinkel 2010年

刚刚停止在WordPress 3.1上为我工作。试图找出到底发生了什么变化。看来它仍然应该工作:分类法和术语条在URL中显示为GET值,但其结果是0个结果
Manny Fleurmond 2011年

我一直在尝试使其工作,但是我唯一的方法是使用parse_query挂钩,检查分类法的查询var并基于此设置分类法和术语查询vars。使用WP 3.1。提交过滤器时,URL中是否应显示分类法和术语?
sanchothefat 2011年

2
对我来说就像一个魅力!确实非常优雅的解决方案。我欠你啤酒:)
Michal Mau

@somatic这很好用,但是有没有办法让$ term-> count只计算该帖子类型的条件?例如,如果我对照片和视频都有自定义分类法,则在查看视频自定义帖子类型时会显示给我,这是两种自定义帖子类型中该术语的帖子总数,而不是仅使用该类别的视频帖子总数术语。
Greenhoe 2015年

13

这是此版本的一个版本,该版本会自动从所有分类法创建并应用过滤器,这些分类法适用于所有使用它们的自定义帖子类型。(令人a目结舌)无论如何,我也对其进行了调整,使其可与wp_dropdown_categories()和wordpress 3.1一起使用。我正在处理的项目称为ToDo,您可以将函数重命名为对您有意义的名称,但这对于自动完成所有工作应该是相当有效的。

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

请注意,我使用的插件添加了“ term_order”作为对术语进行排序的方式,您必须对此进行更改,或者删除该参数以将其回退为默认值。


确实很性感。我收到错误通知,因此我将if(isset($ var))更改为if(isset($ var)&& $ var> 0),以避免尝试查找与“查看全部0”值关联的术语。哦,我必须在todo_convert_restrict函数中返回$ query
helgatheviking 2012年

11

迟到的答案

编辑

我已经写了Filterama,这是一个将以最简单的方式添加此功能的插件。

WordPress 3.5+更新

现在事情变得简单得多,这是一个非常简单的解决方案,如插件或mu-plugin。

它使用尽可能少的资源,仅在所需的屏幕上加载,并为每个自定义分类法添加列+过滤器。

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

    }

}

然后,您只需要一个自定义的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})"
                : ''
        );
    }
}

进行了旋转,但似乎缺少get_select()方法。
Dave Romsey 2013年

@ goto10你是对的。更新。顺便说一句:抓住链接的插件会更容易。一两个星期后,它就会在插件存储库中可用。(已确认)。
kaiser

为了工作,我不得不$this->setup_vars();在开始时使用public function setup()"manage_taxonomies_for_{$this->post_type}_columns"
Christian

但这可能是因为我在主题函数add_action( 'init', array( 'WCM_Admin_PT_List_Tax_Filter', 'init' ) );
Christian

@Christian这不是主题材料。它属于一个插件,如上面的代码所示,当前加载该主题的时间远远早于加载主题的时间。
kaiser

7

我只是想做个快速笔记。在较新版本的WP上,admin上的帖子列表由WP_Posts_List_Table类处理。现在apply_filters代码如下:

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

因此,要添加新列,add_filter挂钩应如下所示:

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

举个例子:

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

现在,对于帖子行。这是处理清单中列数据的代码:

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

为了检索我们的帖子数据,我们必须添加一个动作钩子,如下所示:

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

示例(此示例使用分类法,但您可以查询任何其他内容):

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

在WP 3.2中工作!

custom_post_type:书籍 custom_taxonomy:类型

只是修改说://在这里更改

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

对于WP 3.2及更高版本而言,这是一个很好的解决方案。
petermolnar

它有效,但是__("Show All {$info_taxonomy->label}")使用可翻译字符串的方法错误。
马克·卡普伦

2

这是一种使用strict_manage_posts操作的方法。它似乎对我来说效果很好,并增加了按分类对所有职位类型以及相关分类法进行过滤的功能。

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

一条注释-我尝试限制深度,因为我的某些层次分类法相当大,但没有用-可能是wp_dropdown_categories函数中的错误?


2

我猜这不是众所周知,但是从wordpress 3.5开始,您可以传递'show_admin_column' => trueregister_taxonomy。这有两件事:

  1. 将分类列添加到管理员帖子类型列表视图
  2. 通过在分类法列上单击术语的名称,实际上它将过滤列表至该术语

因此,这与选择功能不完全相同,但功能几乎相同,宽度仅为一行代码。

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

另外,如您所见,还有一个专门用于手动添加分类法列的新过滤器(如果您确实需要)。


1

@somatic的答案的分层版本,按@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);
    }

}
?>

我基本上删除了创建选项的代码,并将其放入自己的函数中。函数“ generate_taxonomy_options”除了采用tax_slug之外,还采用了parent和level参数。该函数假定其为父级0创建选项,它将选择所有根级别术语。在循环中,该函数将递归调用自身,使用该当前术语作为父项并将级别提高一级。它会在您越深越深的树上自动添加刻度线,瞧!


1

@Drew Gourley针对WP 3.3.1的答案的更新(并包含来自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

抱歉,作为新用户,我无法发表评论,但可以发表答案...

从WordPress 3.1(RC 1)开始,Mike的答案(过去几个月来对我的服务是如此出色)对我不再有效;通过任何分类法子项进行限制都会得出空的结果。我尝试了Somatic的更新,效果很好;更好的是,它可以与本版本中已处理的多个分类法查询一起使用。


由于某些原因,躯体版本在3.1中也不起作用
Manny Fleurmond

0

刚刚尝试了Mike和somatic的两个代码,并且想知道如何从每种技术中获得一件事:

使用Mike的代码,它显示带有分层选项的下拉列表,这很有帮助。但为了显示两个下拉菜单,我不得不重复 if ($typenow=='produtos') {...}在函数语句restrict_listings_by_business(),也是if ($pagenow=='edit.php' && ... }convert_business_id_to_taxonomy_term_in_query($query)现在给出了大量的代码功能。

使用躯体代码,我只需要指定分类和我可以看到的分类法即可; $filters = array('taxo1', 'taxo2');

问题:我可以采用躯体方法,也可以选择层次结构吗?

无论如何,非常感谢本教程,对您有很大帮助!


我对分层解决方案的回答
Manny Fleurmond 2011年

0

迈克的教程太棒了!如果我必须自己弄清楚这个功能,我可能不会费心将其添加到我的Media Categories插件中。

就是说,我认为使用parse_query然后查询该词是不必要的。创建您自己的自定义沃克类更干净。也许当他写他的帖子时是不可能的-在我写这篇文章的时候它已经3岁了。

在github上查看这个很棒的代码片段。像超级按钮一样工作,将下拉列表中的ID更改为段,因此无需修改查询即可直接运行。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.