admin管理员组文章数量:1122846
I have created a Custom Post Type called 'listing'
and added a Custom Taxonomy called 'businesses'
. I would like to add a dropdown list of Businesses to the admin list for the Listings.
Here is what this functionality looks like in admin list for Posts (I would like the same for my Custom Post Type):
Here is my current code (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();
}
How can I do add a dropdown list of Businesses to the admin list for the Listings?
I have created a Custom Post Type called 'listing'
and added a Custom Taxonomy called 'businesses'
. I would like to add a dropdown list of Businesses to the admin list for the Listings.
Here is what this functionality looks like in admin list for Posts (I would like the same for my Custom Post Type):
Here is my current code (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();
}
How can I do add a dropdown list of Businesses to the admin list for the Listings?
Share Improve this question edited Nov 4, 2010 at 21:16 MikeSchinkel 37.5k14 gold badges116 silver badges132 bronze badges asked Aug 19, 2010 at 15:13 Taras MankovskiTaras Mankovski 1,5013 gold badges10 silver badges9 bronze badges 2- 8 Thanks for the screenshot, it really helps to have those. – MikeSchinkel Commented Aug 19, 2010 at 17:29
- There is a plugin Admin Taxonomy Filter that can do the exact job. – Anh Tran Commented Sep 20, 2017 at 1:33
17 Answers
Reset to default 150July 2024 UPDATE:
This code no longer works. Tested in the current version of WP at the time of writing (6.5.5). To make it work again, there are a few changes required to the Step 1 code:
name
parameter
In the wp_dropdown_categories()
the name
parameter must be the slug of the taxonomy. So while in this case it doesn't change, it's not quite obvious what other people should be changing it to. Especially because the official docs doesn't mention it:
name
string
Value for the
'name'
attribute of the select element. Default'cat'
.
This could lead to thinking it's a custom string such as "my_select_name"
. To remove confusion, we can just use the variable.
wp_dropdown_categories(array(
'name' => $taxonomy,
...
));
selected
parameter
The selected
parameter must be changed to:
wp_dropdown_categories(array(
'selected' => $wp_query->query_vars['term']?? 0,
...
));
This is because the term
is defined in the query_vars
instead of query
. If the term doesn't exist in the query_vars
then most likely a term wasn't selected, so we can just use the null coalescing operator to test for that and if it is null|undefined
then just select the show all option with the 0
value.
value_field
parameter
A new parameter was added in WP 4.2.0: the value_field
.
Using this parameter, we can now tell the WP to use a specific "term field" to be used to populate the option values. From the docs:
value_field
string
Term field that should be used to populate the
'value'
attribute of the option elements. Accepts any valid term field: 'term_id'
,'name'
,'slug'
,'term_group'
,'term_taxonomy_id'
,'taxonomy'
,'description'
,'parent'
,'count'
. Default'term_id'
.
Adding slug
to this parameter will populate the option values with the term slugs. Because the slug is needed for the filter function to work, then this parameter basically makes the filters work just from the Step 1 code without the need for Step 2.
So Step 2 can be disregarded if using value_field
.
wp_dropdown_categories(array(
'value_field' => 'slug',
...
));
I have left the original code below, so make these changes as detailed above to the code below.
UPDATE: I've included a new complete answer but even so I've left my original response at the bottom to which the first few comments reference.
Hi @tarasm:
Although I said it shouldn't be hard it is a little involved. But before we dig into the code...
The Screenshots:
...let's check out some screen shots for the finished product:
Listings list page with No Filtering:
(source: mikeschinkel.com)
Listings list page With Filtering:
(source: mikeschinkel.com)
The Code
So here we go... (Note: I used a singular form for the taxonomy name of business
; I hope that matches your. From lots of experience with both WordPress and database development in the past I believe it is best to do it this way.)
Step #1: The restrict_manage_posts
action hook.
First thing you need to do is to hook the restrict_manage_posts
action which has no parameters and is called from /wp-admin/edit.php
(in v3.0.1 that call is on line 378.) This will allow you to generate the drop down select at the appropriate location above the list of Listing 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
));
}
}
We start by checking the $typenow
variable to ensure we are in fact on a post_type
of listing
. If you don't you'll get this drop down for all post types which in some cases is what you want, but not this case.
Next we load information about the business taxonomy using get_taxonomy()
. We need it to retrieve the label for the taxonomy (i.e. "Businesses"; we could have hard-coded, but that's not very good if you need to internationalize later.) Then we call wp_dropdown_categories()
with all the appropriate arguments in the $args
array to generate the drop down
<?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
));
But what are the appropriate arguments? Let's look at each individually:
show_optional_all
- Pretty straightforward, it's what is displayed in the drop down at first and when there has been no filtering applied. In our case it's going so be "Show All Businesses" but we could have called it "Listings for All Businesses" or whatever you like.taxonomy
- This arguments tells the function what taxonomy to pull terms from even though the function hascategories
in its name. In v2.8 and earlier WordPress didn't have custom taxonomies but when they were added the team decided it would just be easier to add an taxonomy argument to this function than to create another function with another name.name
- This argument allows you to specify the value that WordPress with use for thename
attribute of the <select> element generated for the drop down. Just in case it isn't obvious this is also the value that will be used in the URL when filtering.orderby
- This argument tells WordPress how to order the results alphabetically. In our case we specified to order buy thename
of the terms in the taxonomy, i.e. the business names in this case.selected
- This argument is needed so that the drop down can show the current filter in the drop down. It should be theterm_id
from the selected taxonomy term. In our case it might be theterm_id
from "Business #2". Where do we get this value? From WordPress' global variable$wp_query
; it has a propertyquery
that contains an array of all the URL parameters and their values (unless some wayward plugin modified it already, of course.) Given how WordPress processes things there will be aterm
URL parameter passed on the URL when the user clicks the filter button if the user selected a valid term (i.e. one of the listed businesses).hierarchical
- By setting this totrue
you tell the function to respect the hierarchical nature of the taxonomy and display them in a tree view if the terms (businesses) in fact have children. For a screen shot to see what this looks like, see below.depth
- This argument collaborates with thehierarchical
argument to determine how many levels deep the function should go in displaying children.show_count
- Iftrue
this argument will display a count posts within parentheses to the left of the term name within the drop down. In this case it would display a count of listings associated with a businesses. For a screen shot to see what this looks like, see below.hide_empty
- Finally, if there are terms in the taxonomy that are not associated with a post (i.e. businesses not associated with a listing) then setting this totrue
will omit them from being included in the drop down.
(source: mikeschinkel.com)
Step #2: The parse_query
filter hook.
Next we call our attentions to the parse_query
filter hook which has one parameter ($query
) and is called from /wp-includes/query.php
(in v3.0.1 that call is on line 1549.) It is called when WordPress has finished inspecting the URL and setting all appropriate values in the currently active $wp_query
including things like $wp_query->is_home
and $wp_query->is_author
, etc.
After the parse_query
filter hook runs WordPress will call get_posts()
and load up a list of posts based on what is specified in the currently active $wp_query
. So parse_query
is often a great place to get WordPress to change it's mind about which posts it is going to load.
In your use-case we want to get WordPress to filter based on the businesses selected; i.e. to display only those Listings which have been associated with the the selected business (I'd say "...only those Listings that have been "categorized" by the selected business" but that's not technical correct; category
is it's own taxonomy on peer with business
except that category
is built into WordPress and business
is custom. But for those familiar with categorizing posts this may help you understand as they work almost identically. But I digress...)
On to the code. The first thing we do is grab a reference to the currently active $wp_query
's query_vars
so that it's more convenient to work with, just like how its done within WordPress' own parse_query()
function. Unlike $wp_query->query
which is used to mirror the parameters passed on the URL the $wp_query->query_vars
array is used to control the query that WordPress runs and is expected to be modified. So if you need to modify one, that'd be the one (at least I think that is the different between the two; if anyone knows otherwise please let me know so I can update this!)
<?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;
}
}
Next we test $pagenow
to ensure that we are indeed loading WordPress from the URL path /wp-admin/edit.php
. We do this to keep from accidentally screwing up queries on other pages. We also check to make sure that we have both business
as a taxonomy
element and a term
element too. (Note taxonomy
and term
are a pair; they are used together to allow querying of a taxonomy term; gotta have both or WordPress doesn't know which taxonomy to inspect.)
You might wonder how business
turned up in the taxonomy
element of the query_vars
array. What we wrote in our parse_query
hook triggered WordPress' internal magic that was laid in waiting when you registered the "business
" taxonomy by setting query_var
to be true (register_taxonomy()
copies the name of the taxonomy as its query_var
; you can change it of course but unless you have a conflict it's best to stick with the same):
<?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
));
}
Now WordPress' $wp_query was written to use slugs for standard taxonomy filtered queries, not taxonomy term IDs. For this use-case what we really need to make our filtering query work are these:
taxonomy
: business
term
: business-1 (i.e. theslug
)
Not these:
taxonomy
: business
term
: 27 (i.e. theterm_id
)
Interestingly and unfortunately the drop-down generated by wp_dropdown_categories()
set the <option>
's value
attribute to the term's(/business') term_id
, not the term slug
. So we need to convert $wp_query->query_vars['term']
from a numeric term_id
to it's string slug
as following in the snippet snagged from above (Note this is not the most performant way to query a database but until WordPress adds support for term_ids into its query that's the best we can do!):
<?php
$term = get_term_by('id',$qv['term'],'business');
$qv['term'] = $term->slug;
And that's it! With those two functions you get the filtering you desire.
BUT WAIT, THERE'S MORE! :-)
I went ahead and added a "Businesses" column to your Listing list because, well, I knew it was going to be your next question. Without having a column for what you filter it can be very confusing for the end user. (I struggled with it myself, and I was the coder!) You can of course already see the "Businesses" column in the prior screen shots above.
Step #3: The manage_posts_columns
filter hook.
To add a column to the post list takes calling two (2) more hooks. The first one is manage_posts_columns
or the post type-specific version manage_listing_posts_columns
that I called instead. It accepts one parameter (posts_columns
) and is called from /wp-admin/includes/template.php
(in v3.0.1 that call is on line 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;
}
Your manage_posts_columns
hook function gets passed an array of columns where the value is the displayed column header and the key is the internal column identifier. Standard column identifiers can include these and more: 'cb'
, 'title
', 'author'
, ``'date'`, etc.
'cb'
, is the checkbox
column and both 'title'
and 'date'
refer to post_title
and post_date
from the wp_posts
table, respectively. 'author'
of course is the post_author
field after the author name is retrieved from the wp_users
table.
(source: mikeschinkel.com)
For the manage_posts_columns
hook we are simply wanting to insert our column businesses
into the $posts_columns
array before 'author'
, assuming some other plugin hasn't removed author
from the list yet!
$new_posts_columns['businesses'] = 'Businesses';
(Note as I wrote add_businesses_column_to_listing_list()
it occurred to me that PHP must have an easier way to insert a value into an associative array in the proper order?!? Or at least there's got to be a function in WordPress core to do it? But since Google let me down so I went with what worked. If anyone has any suggested alternatives I'll be all ears and appreciative in advance!)
Which finally brings us to...
Step #4: The manage_posts_custom_column
action hook
The second thing of two (2) we need to do to make our businesses display in the column is to actually output the name of each of the associated businesses using the manage_posts_custom_column
action hook. This hook accepts two (2) parameters (column_id
and post_id
) and is also called from /wp-admin/includes/template.php
(in v3.0.1 that call is on line 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;
}
}
}
This hook is called for each column for each post(/business) row. We first verify that we are indeed working with only the listing
custom post type and then we use a switch
statement to test against the column_id
. I chose switch
because this hook is often used to generate output for many different columns, especially if we use one function for many different post types which might look something like this:
<?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;
}
}
Inspecting our use-case just a little closer you see the get_the_terms()
function which simply returns the list of terms for this taxonomy (i.e. businesses for this listing.) Here get the permalink for the term's front-end web page that normally lists posts that are associated with the term but of course could might differently depending on the theme and/or plugins installed.
We use the permalink to hyperlink the term just because I like to hyperlink things. We then merge all the hyperlinked terms(/businesses) together separated with the pipe ('|
') character and output to the PHP buffer which sends it to the user's browser/HTTP client:
<?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);
}
NOW we are finally done.
Summary
So in summary you need to use the following four (4) hooks to get both a filter and a related column in the custom posts list page (Oh, it will also work with Posts and Pages.) They are:
- Step #1: The
restrict_manage_posts
action hook. - Step #2: The
parse_query
filter hook. - Step #3: The
manage_posts_columns
filter hook. - Step #4: The
manage_posts_custom_column
action hook
Where to download the code
But if I forced you to read through all the above then I would certainly not be a very nice person if I also made you dig out the code just to be able to try it out! But contrary to what some people say, I am nice. So here ya go:
- Download the Code at: http://gist.github.com/541505
NOTE to @tarasm: I included hooks for a register_post_type()
and register_taxonomy()
so that others could try this out without having to recreate them. You'll probably want to delete those two function calls before you test this out.
THE END
Original Response:
Hi @tarasm:
Are you looking for one drop down at the top like this screen or are you looking for one drop down per post record and if so how would you expect the latter to work?
(source: mikeschinkel.com)
If the former, take a look at this answer to the question How to sort the admin area of a Wordpress custom post type by a custom field? If that is what you need I can provide more specifics related to taxonomy.
Just wanted to share an alternative implementation. I didn't have Mike's incredible tutorial when I was figuring this out, so my solution is a little different. Specifically, I'm going to simplify Mike's step #1 and eliminate step #2 - the other steps are still applicable.
In Mike's tutorial, using wp_dropdown_categories()
saves us some manual list-building, but requires some complicated conditional query modification (step #2) to handle its use of ID instead of slug. Not to mention the difficulty of modifying that code to deal with other scenarios, like multiple taxonomy filters..
Another approach is to simply not use the flawed wp_dropdown_categories()
at all, but instead to build our own dropdown select lists from scratch. It's not that complicated, takes less than 30 lines of code, and doesn't require hooking parse_query
at all:
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>";
}
}
}
By simply plugging the desired taxonomies into the $filters
array, you can quickly output multiple taxonomy filters. They appear exactly the same as those in Mike's screenshots. Then you can follow through with step #3 and #4.
Here is a version of this that automatically creates and applies filters from all taxonomies that apply to all custom post types which use them. (what a mouthful) Anyways, I also tweaked it so it works with wp_dropdown_categories() and wordpress 3.1. The project I'm working on is called ToDo, you can rename the functions to something that makes sense for you, but this should pretty much work for everything automatically.
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');
Note that I'm using a plugin that adds 'term_order' as a way to order terms, you'll have to change that, or remove that argument to fallback to the default.
Late answer
Edit
I've written Filterama, a plugin that will add this functionality the easiest possible way.
Update for WordPress 3.5+
Now that things are much easier, here's a very simple solution as plugin or mu-plugin.
It uses as less resources as possible, loads only on the needed screens and adds Columns + Filters for every custom taxonomy.
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,
) );
}
}
}
And then you just need a customized Walker class.
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( ' ', $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']
? " ({$term->count})"
: ''
);
}
}
I just wanted to make a quick note. On newer versions of WP, post listings on admin are handled by the WP_Posts_List_Table class. The apply_filters code is now as follows:
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 );
So to add new columns an add_filter hook should be like this:
add_filter( 'manage_posts_columns', 'my_add_columns', 10, 2);
Here goes an example:
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;
}
}
Now, for the post rows. This is the code that handles column data on the listings:
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
In order to retrieve our posts data, we have to add an action hook like this:
add_action( "manage_(here_goes_your_post_type)_posts_custom_column", "my_posttype_add_column", 10, 2);
Example (this example uses taxonomies, but you could query any other stuff):
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;
}
}
WORKS IN WP 3.2!
custom_post_type: books custom_taxonomy: genre
Only modify were it says: // change HERE
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');
I had to work on a similar feature not so long ago, as I wasn't satisfied with the answers, here is my alternative. Year is 2021.
I wanted something dumb and simple to implement. Quickly and efficiently getting all custom taxonomies from each custom post type and adding them as filters options.
There was a few prerequisite:
- I wanted to step away from using global variables.
- Code needed to be portative, no hardcoded variables, to be reusable.
- Having some kind visible hierarchy, perfect for heavy terms related taxonomies.
- Needed to respect taxonomy visibility choice. (eg:
show_admin_column
argument parameter from theregister_taxonomy
function. - Displaying post count.
- The overall appearance to be matching with WordPress.
I've made it into a plugin, for an easier integration, you can get the latest version @ https://wordpress.org/plugins/cpt-admin-taxonomy-filtering/.
Filter with term hierarchy & posts count | Multiple custom post type filters |
---|---|
If you just want to add it to your function.php
, copy and paste the following script.
Requires at least WordPress
4.8.0
& PHP:4.0
.
<?php
add_action( 'restrict_manage_posts', 'cpt_admin_taxonomy_filtering' );
if ( ! function_exists( 'cpt_admin_taxonomy_filtering' ) ) {
function cpt_admin_taxonomy_filtering() {
/**
* Get the current screen object.
*
* @link https://developer.wordpress.org/reference/functions/get_current_screen/
*/
$screen = get_current_screen();
// Single out WordPress default posts types
$restricted_post_types = array(
'post',
'page',
'attachment',
'revision',
'nav_menu_item',
);
if ( 'edit' === $screen->base && ! in_array( $screen->post_type, $restricted_post_types ) ) {
/**
* Return the names or objects of the taxonomies which are registered for the requested object or object type, such as a post object or post type name.
*
* @link https://developer.wordpress.org/reference/functions/get_object_taxonomies/
*/
$taxonomies = get_object_taxonomies( $screen->post_type, 'objects' );
// Loop through each taxonomy
foreach ( $taxonomies as $taxonomy ) {
if ( $taxonomy->show_admin_column ) {
/**
* Displays or retrieves the HTML dropdown list of categories.
*
* @link https://developer.wordpress.org/reference/functions/wp_dropdown_categories/
*/
wp_dropdown_categories(
array(
'show_option_all' => $taxonomy->labels->all_items,
'pad_counts' => true,
'show_count' => true,
'hierarchical' => true,
'name' => $taxonomy->query_var,
'id' => 'filter-by-' . $taxonomy->query_var,
'class' => '',
'value_field' => 'slug',
'taxonomy' => $taxonomy->query_var,
'hide_if_empty' => true,
)
);
};
};
};
};
};
This is not well known I guess, but as of wordpress 3.5, you can pass 'show_admin_column' => true
to register_taxonomy
. This does 2 things:
- Adds the taxonomy column to the admin post type list view
- By clicking the name of the term on the taxonomy column, it will in fact filter the list to that term.
So, not exactly the same as having a select, but almost the same functionality, width just one row of code.
https://make.wordpress.org/core/2012/12/11/wordpress-3-5-admin-columns-for-custom-taxonomies/
Also, as you can read, there is a new filter tailored for manual adding taxonomy column (if you really need to).
Thank you guys for all the answers. I know this an old question, but I would like to add the more simple solution that can be used nowadays. This will only require 2 steps and will use more of the available core features. Hope this will help someone.
Step 1: add 'show_admin_column' => true
to your register_taxonomy
function.
This will add a column to the list view containing links to filter the list by that term. This can be applied for both hierarchical and non-hierarchical taxonomies.
Example:
register_taxonomy( 'custom_cat', array( 'custom_post_type' ), array(
'hierarchical' => true,
'labels' => array(
'name' => __( 'Categories', 'iside' ),
'singular_name' => __( 'Category', 'iside' ),
'search_items' => __( 'Search Categories', 'iside' ),
'all_items' => __( 'All Categories', 'iside' ),
'parent_item' => __( 'Parent Category', 'iside' ),
'parent_item_colon' => __( 'Parent Category:', 'iside' ),
'edit_item' => __( 'Edit Category', 'iside' ),
'update_item' => __( 'Update Category', 'iside' ),
'add_new_item' => __( 'Add New Category', 'iside' ),
'new_item_name' => __( 'New Category', 'iside' ),
'menu_name' => __( 'Categories', 'iside' ),
),
'public' => true,
'publicly_queryable'=> true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_nav_menus' => true,
'show_in_rest' => true,
'show_tagcloud' => false,
'show_in_quick_edit'=> true,
'show_admin_column' => true, // <-- the magic applied here
'query_var' => true,
) );
Step 2: add the taxonomy dropdown through the restrict_manage_posts
filter
This will add a select dropdown to the filter options on top. It will use the default wp_dropdown_categories
function to make it easier. Please note that we need to set the name of the dropdown to the query_var we use for the taxonomy. Also note that the value_field
needs to be set to the slug (by default this will be the term_id).
Example:
add_action( 'restrict_manage_posts', 'iside_add_filter_to_admin', 10, 2 );
function iside_add_filter_to_admin( $post_type = 'post', $which = 'top' ) {
if( $post_type == 'custom_post_type' ) {
$selected = isset( $_GET['custom_cat'] ) ? esc_attr($_GET['custom_cat']) : 0;
wp_dropdown_categories(array(
'show_option_all' => __( 'Show All Categories', 'iside' ),
'taxonomy' => 'custom_cat',
'name' => 'custom_cat', // <-- make sure it will match the query_var
'orderby' => 'name',
'selected' => $selected,
'hierarchical' => true,
'depth' => 3,
'show_count' => true,
'hide_empty' => true,
'value_field' => 'slug', // <-- use slug instead of term_id
));
}
}
That's it. No need to add more :-)
Here's a way to do it using the restrict_manage_posts action. It seems to work well for me and adds the ability to filter by taxonomy for all post types and there related taxonomies.
// 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(' ', $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 .= ' ('. $category->count .')';
if ( $args['show_last_update'] ) {
$format = 'Y-m-d';
$output .= ' ' . gmdate($format, $category->last_update_timestamp);
}
$output .= "</option>\n";
}
}
One note - I tried restricting the depth because some of my hierarchical taxonomies are quite large but it didn't work - could be a bug in the wp_dropdown_categories function?
Hierarchical version of @somatic's answer, as requested by @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);
}
}
?>
I basically removed the code that created the options and put that in it's own function. The function 'generate_taxonomy_options', in addition of taking the tax_slug, also takes a parent and level parameter. The function assumes that its creating options for the parent 0, which will select all the root level terms. In the loop the function will recursively call itself, using that current term as a parent and increasing the level by one. It automatically adds ticks to the side the deeper you go down the tree and voila!
Update of @Drew Gourley's answer for WP 3.3.1 (and incorporating code from 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(' ', $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";
}
}
Simply add this to your functions.php or plugin code (and replace YOURCUSTOMTYPE and YOURCUSTOMTAXONOMY). (I got the code from generatewp)
add_action( 'restrict_manage_posts', 'filter_backend_by_taxonomies' , 99, 2);
function filter_backend_by_taxonomies( $post_type, $which ) {
// Apply this to a specific CPT
if ( 'YOURCUSTOMTYPE' !== $post_type )
return;
// A list of custom taxonomy slugs to filter by
$taxonomies = array( 'YOURCUSTOMTAXONOMY' );
foreach ( $taxonomies as $taxonomy_slug ) {
// Retrieve taxonomy data
$taxonomy_obj = get_taxonomy( $taxonomy_slug );
$taxonomy_name = $taxonomy_obj->labels->name;
// Retrieve taxonomy terms
$terms = get_terms( $taxonomy_slug );
// Display filter HTML
echo "<select name='{$taxonomy_slug}' id='{$taxonomy_slug}' class='postform'>";
echo '<option value="">' . sprintf( esc_html__( 'Category', 'text_domain' ), $taxonomy_name ) . '</option>';
foreach ( $terms as $term ) {
printf(
'<option value="%1$s" %2$s>%3$s (%4$s)</option>',
$term->slug,
( ( isset( $_GET[$taxonomy_slug] ) && ( $_GET[$taxonomy_slug] == $term->slug ) ) ? ' selected="selected"' : '' ),
$term->name,
$term->count
);
}
echo '</select>';
}
}
Apologies for the fact that, as a new user, I can't post comments but I can post an answer...
As of WordPress 3.1 (RC 1) Mike's answer (which has served me so well for the past couple for months) no longer works for me; restricting by any taxonomy child gives an empty result. I tried Somatic's update and it worked great; even better, it works with multiple taxonomy queries which has been worked into this release.
Just tried both codes, from Mike and somatic and was wondering on how to get one thing from each technique:
With Mike's code, it shows the dropdown list with the hierarchical option, which helps a lot. But in order to display two dropdowns i had to duplicate the if ($typenow=='produtos') {...}
statement in the function restrict_listings_by_business()
and also the if ($pagenow=='edit.php' && ... }
in the convert_business_id_to_taxonomy_term_in_query($query)
function which now gives a lot of code.
With somatic's code i just need to specify the taxonomies i'd like to see as dropdowns and bam, works; $filters = array('taxo1', 'taxo2');
Question: can i get somatic's approach and also have the hierarchical option?
Thanks a lot anyway for this tutorial, helped a lot!
Mike's tutorial on this is great! I probably would not have bothered adding this functionality to my Media Categories plugin if I would have had to figure it out on my own.
That said, I think using parse_query
and then get then query for the term isn't necessary. It's cleaner for create your own custom walker class. Maybe that wasn't possible when he wrote his post - its 3 years old at the time of my writing this.
Checkout this great snippet on github. Works like a charm, changes the ID's in the dropdown values into slugs, so it just works natively without modifying the query.
https://gist.github.com/stephenh1988/2902509
This is a powerful little snippet to allow filtering your post or custom post type by a specific taxonomy term in the WordPress admin.
/* Filter CPT via Custom Taxonomy */
function rave_core_backend_by_portfolio_taxonomies( $post_type, $which ) {
// Apply this to a specific CPT
if ( 'portfolio' !== $post_type )
return;
// A list of custom taxonomy slugs to filter by
$taxonomies = array( 'portfolio_cat' );
foreach ( $taxonomies as $taxonomy_slug ) {
// Retrieve taxonomy data
$taxonomy_obj = get_taxonomy( $taxonomy_slug );
$taxonomy_name = $taxonomy_obj->labels->name;
// Retrieve taxonomy terms
$terms = get_terms( $taxonomy_slug );
// Display filter HTML
echo "<select name='{$taxonomy_slug}' id='{$taxonomy_slug}' class='postform'>";
echo '<option value="">' . sprintf( esc_html__( 'All %s', 'rave-core' ), $taxonomy_name ) . '</option>';
foreach ( $terms as $term ) {
printf(
'<option value="%1$s" %2$s>%3$s (%4$s)</option>',
$term->slug,
( ( isset( $_GET[$taxonomy_slug] ) && ( $_GET[$taxonomy_slug] == $term->slug ) ) ? ' selected="selected"' : '' ),
$term->name,
$term->count
);
}
echo '</select>';
}
}
add_action( 'restrict_manage_posts', 'rave_core_backend_by_portfolio_taxonomies' , 99, 2);
本文标签: pluginsAdding a Taxonomy Filter to Admin List for a Custom Post Type
版权声明:本文标题:plugins - Adding a Taxonomy Filter to Admin List for a Custom Post Type? 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736301298a1931129.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论