问题描述

我创建了一个名为'listing'的自定义帖子类型,并添加了一个名为'businesses'的自定义分类。我想在 「列表」 的管理列表中添加一个 「企业」 下拉列表。

这是功能在管理员列表中的功能 (我想对我的自定义帖子类型是一样的):

这是我现在的代码 (And here is the same code on 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();
}

如何添加企业的下拉列表到列表的管理列表?

最佳解决方案

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


嗨 @tarasm:

虽然我说这不是很难,但有一点涉及。但是在我们挖掘代码之前…

截图:

… 我们来看看成品的一些屏幕快照:

没有过滤的列表页面:

列表列表页面过滤:

代码

所以在这里我们去…(注意:我使用了一个单数形式的分类名称 business; 我希望匹配你。从很多经验与 WordPress 和数据库开发过去我认为最好这样做办法。)

步骤#1:restrict_manage_posts 动作挂钩。

你需要做的第一件事情就是钩子没有参数,被称为从/wp-admin/edit.php(在调用上线 378 V3.0.1) 这将让你产生压降以高于合适的位置向下选择的 restrict_manage_posts 行动上市信息清单。

<?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”; 我们可以使用 hard-coded,但是如果您需要稍后进行国际化,则不太好) 。然后,我们将 $args 数组中的所有适当参数称为 wp_dropdown_categories(),以生成下拉列表

<?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 与< select> 的 name 属性一起使用的值。生成的元素为下拉菜单。为了防止这种情况不明显,这也是过滤时在 URL 中使用的值。
  •  orderby – 此参数告诉 WordPress 如何按字母顺序排列结果。在我们的例子中,我们指定订购 name 的分类术语,即这种情况下的商业名称。
  •  selected – 需要此参数,以便下拉列表可以在下拉列表中显示当前过滤器。它应该是所选分类术语中的 term_id 。在我们的例子中,可能是来自 「Business#2」 的 term_id 。我们在哪里得到这个价值?从 WordPress 的全局变量 $wp_query; 它具有一个属性 query,其中包含所有的 URL 参数及其值的数组 (除非有一些方便的插件已经修改了,当然) 。如果 WordPress 处理的东西,当用户点击时会传递一个 term URL 参数如果用户选择了有效的术语 (即所列商业之一),则过滤器按钮。
  •  hierarchical – 通过将其设置为 true,您可以告知功能是否遵守分类法的层次性质,如果术语 (商业) 实际上有孩子,则将其显示在树状视图中。为了看到这样的屏幕截图,见下文。
  •  depth – 此参数与 hierarchical 参数进行协作,以确定函数在显示子级时应该有多少级别。
  •  show_count – 如果 true 此参数将在下拉列表中的术语名称左侧的括号内显示计数帖子。在这种情况下,它将显示与企业相关联的列表数。为了看到这样的屏幕截图,见下文。
  •  hide_empty – 最后,如果分类中没有与某个职位相关联的术语 (即与列表无关的业务),则将其设置为 true 将不会将其包含在下拉列表中。

步骤#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 改变它将要加载哪些帖子的好地方。

在您的 use-case 中,我们希望让 WordPress 根据所选商家进行过滤; 即只显示与所选业务相关联的列表 (我会说 「只有所选业务已经”categorized” 的列表」,但这并不是技术上正确的; category 是同行的自己的分类法 business 除了 category 内置在 WordPress 中,business 是习惯的,但对于熟悉帖子的人来说,这可能有助于您理解,因为他们的工作几乎相同,但我离题…)

对代码。我们首先要做的是参考当前活动的 $wp_queryquery_vars,这样它更方便使用,就像它在 WordPress 自己的 parse_query()功能中所做的一样。与用于镜像在 URL 上传递的参数的 $wp_query->query 不同,$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 路径/wp-admin/edit.php 加载 WordPress 。我们这样做是为了避免意外地拧紧其他页面上的查询。我们还检查,确保我们同时具有 business taxonomy 元素和 term 元素。 (注意 taxonomyterm 是一对; 它们一起使用以允许查询分类术语; 必须同时使用或 WordPress 不知道要检查哪种分类法。)

您可能会想 business query_vars 阵列的 taxonomy 元素如何出现。我们在 parse_query 钩子中写入的内容是通过将 query_var 设置为真,将 「business」 分类为 「business」,将 WordPress 的内部魔术放在等待中 (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 写入使用 slugs 标准分类过滤查询,而不是分类术语 ID 。对于这个 use-case,我们真正需要使我们的过滤查询工作是这些:

taxonomy: business

term: business-1 (i.e. the slug)

不是这些

taxonomy: business

term: 27 (i.e. the term_id)

有趣的是,不幸的是,wp_dropdown_categories()产生的 drop-down 将<option>value 属性设置为术语’s(/business’)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” 列,因为我知道这将是您的下一个问题。没有一列您所筛选的列可能会让最终用户感到困惑。 (我自己努力,我是编码器!) 您可以在上面的屏幕截图中看到”Businesses” 列。

步骤 3:manage_posts_columns 过滤钩。

要向列表中添加列可以调用两个 (2) 个更多的钩子。第一个是 manage_posts_columns 或者我调用 type-specific 版本的 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',「’date’」 等

 'cb'checkbox 色谱柱,'title''date'都是分别来自 wp_posts 表的 post_titlepost_date'author'当然是 post_author 字段后,作者姓名从 wp_users 表中检索。

对于 manage_posts_columns 钩子,我们只是希望在'author'之前将 businesses 列插入到 $posts_columns 数组中,假设一些其他插件尚未从列表中删除 author

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

(注意,我写的是 add_businesses_column_to_listing_list(),我发现,PHP 必须有一个更简单的方法来以正确的顺序将值插入到关联数组中?!或者至少在 WordPress 核心中必须有一个功能吗?但是谷歌让我失望,所以我去做了什么工作,如果有任何建议的替代方案,我会全部耳朵和提前感谢!)

哪些最终带给我们…

步骤#4:manage_posts_custom_column 动作钩

我们需要做的第二件事情 (2) 使我们的业务显示在列中,实际上是使用 manage_posts_custom_column 动作挂钩输出每个相关业务的名称。该钩子接受两个参数 (column_idpost_id),并且也从/wp-admin/includes/template.php 调用 (在 v3.0.1 中,调用在第 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;
        }
    }
}

为每个 post(/ business) 行的每个列调用此钩子。我们首先验证我们确实只使用 listing 自定义帖子类型,然后我们使用 switch 语句来测试 column_id 。我选择了 switch,因为这个钩子通常用于为许多不同的列生成输出,特别是如果我们为许多不同的 post 类型使用一个函数,可能看起来像这样:

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

检查我们的 use-case,您会看到 get_the_terms()功能,它可以简单地返回此分类法的术语列表 (即此列表的商家) 。这里获得通常列出与该术语相关联的帖子的 front-end 网页的固定链接但是当然可能会因安装的主题和/或插件而有所不同。

我们使用永久链接超链接这个术语,只是因为我喜欢超链接的东西。然后,我们将所有超链接术语 (/业务) 合并在一起,与管道 (‘|‘) 字符分开并输出到 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 自定义帖子类型的管理区域?如果这是你需要的,我可以提供更多关于分类学的细节。

次佳解决方案

只是想分享一个替代实现。当我想到这个时,我没有 Mike 的令人难以置信的教程,所以我的解决方案有点不同。具体来说,我将简化迈克的步骤#1,并消除步骤#2 – 其他步骤仍然适用。

在 Mike 的教程中,使用 wp_dropdown_categories()为我们提供了一些手册 list-building,但需要进行一些复杂的条件查询修改 (步骤 2) 来处理其使用 ID 而不是 slug 。更不用说修改该代码以处理其他场景的困难,如多个分类过滤器。

另一种方法是根本不使用有缺陷的 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 。

第三种解决方案

这是一个自动创建和应用所有分类法的过滤器的版本,适用于使用它们的所有自定义帖子类型。 (什么嘴巴) 无论如何,我也调整它,所以它适用于 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’ 作为一种方式来排序条款,您必须更改该方法,或者将该参数移除回到默认值。

第四种方案

迟到的答案

Edit

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

第五种方案

我只想快速注意一下。在较新版本的 WP 中,管理员的帖子列表由 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;
  }
}

第六种方案

工作在 WP 3.2!

custom_post_type:books 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');

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。