My Wordpress Plugin is giving me the WSOD - wordpress

I followed this tutorial,http://wp.tutsplus.com/tutorials/plugins/a-guide-to-wordpress-custom-post-types-creation-display-and-meta-boxes/, I thought very closely but when I finished it, my plugin works but it gives every other page on the site the WSOD! Once I deactivate the plugin, my other pages work again. I am running this on my mac using MAMP if that helps at all. I wanted to get it all finished before I upload and test online even though my site isn't live.
Below is my code. Any ideas on what the heck I did wrong? Thank you so much for any help you can give me.
<?php
/*
Plugin Name: NM Portfolio
Plugin URI: http://work.nickmoyer.net
Description: Declares a plugin that will create a custom post type displaying movie reviews.
Version: 1.3
Author: Nick Moyer
Author URI: http://work.nickmoyer.net
License: GPLv2
*/
// Create a Custom Post Type
add_action( 'init', 'create_nm_portfolio' );
function create_nm_portfolio() {
register_post_type( 'nm_portfolio',
array(
'labels' => array(
'name' => 'NM Portfolio',
'singular_name' => 'NM Portfolio',
'add_new' => 'Add New',
'add_new_item' => 'Add New Portfolio Project',
'edit' => 'Edit',
'edit_item' => 'Edit Portfolio Project',
'new_item' => 'New Portfolio Project',
'view' => 'View',
'view_item' => 'View Portfolio Project',
'search_items' => 'Search Portfolio Projects',
'not_found' => 'No Portfolio Projects found',
'not_found_in_trash' =>
'No Portfolio Projects found in Trash',
'parent' => 'Parent Portfolio Project'
),
'public' => true,
'menu_position' => 15,
'supports' =>
array( 'title', 'editor', 'thumbnail' ),
'rewrite' => array('slug' => 'portfolio'),
'taxonomies' => array( '' ),
'has_archive' => true
)
);
}
// Creating Meta Box Fields for Custom Post Types
add_action( 'admin_init', 'my_admin' );
function my_admin() {
add_meta_box( 'nm_portfolio_cleint_meta_box','Portfolio Project Client Info','display_nm_portfolio_client_meta_box','nm_portfolio', 'normal', 'high' );
}
function display_nm_portfolio_client_meta_box( $nm_portfolio ) {
// Retrieve current name of the Director and Movie Rating based on review ID
$nm_clients = esc_html( get_post_meta( $nm_portfolio->ID,'nm_clients', true ) );
?>
<table>
<tr>
<td style="width: 100%">Client Name</td>
<td>
<input type="text" size="80" name="nm_portfolio_clients" value="<?php echo $nm_clients; ?>" />
</td>
</tr>
</table>
<?php }
add_action( 'save_post','add_nm_portfolio_fields', 10, 2 );
function add_nm_portfolio_fields( $nm_portfolio_id,$nm_portfolio ) {
// Check post type for movie reviews
if ( $nm_portfolio->post_type == 'nm_portfolio' ) {
// Store data in post meta table if present in post data
if ( isset( $_POST['nm_portfolio_clients'] ) && $_POST['nm_portfolio_clients'] != '' ) {
update_post_meta( $nm_portfolio_id, 'nm_clients', $_POST['nm_portfolio_clients'] );
}
}
}
// Custom Template Dedicated to Custom Post Types
add_filter( 'template_include','include_template_function', 1 );
function include_template_function( $template_path ) {
if ( get_post_type() == 'nm_portfolio' ) {
if ( is_single() ) {
// checks if the file exists in the theme first,
// otherwise serve the file from the plugin
if ( $theme_file = locate_template( array ( 'single-nm_portfolio.php' ) ) ) {
$template_path = $theme_file;
} else {
$template_path = plugin_dir_path( __FILE__ ) . '/single-nm_portfolio.php';
}
}
elseif ( is_archive() ) {
if ( $theme_file = locate_template( array ( 'archive-nm_portfolio.php' ) ) ) {
$template_path = $theme_file;
} else { $template_path = plugin_dir_path( __FILE__ ) . '/archive-nm_portfolio.php';
}
}
return $template_path;
}
// Displaying Additional Columns
add_filter( 'manage_edit-nm_portfolio_columns', 'my_columns' );
function my_columns( $columns ) {
$columns['nm_portfolio_clients'] = 'Clients';
unset( $columns['comments'] );
return $columns;
}
add_action( 'manage_posts_custom_column', 'populate_columns' );
function populate_columns( $column ) {
if ( 'nm_portfolio_clients' == $column ) {
$nm_clients = esc_html( get_post_meta( get_the_ID(), 'nm_clients', true ) );
echo $nm_clients;
}
}
add_filter( 'manage_edit-nm_portfolio_sortable_columns', 'sort_me' );
function sort_me( $columns ) {
$columns['nm_portfolio_clients'] = 'nm_portfolio_clients';
return $columns;
}
add_filter( 'request', 'column_ordering' );
add_filter( 'request', 'column_orderby' );
function column_orderby ( $vars ) {
if ( !is_admin() )
return $vars;
if ( isset( $vars['orderby'] ) && 'nm_portfolio_clients' == $vars['orderby'] ) {
$vars = array_merge( $vars, array( 'meta_key' => 'nm_clients', 'orderby' => 'meta_value' ) );
}
return $vars;
}
//Creating Filters With Custom Taxonomy
add_action( 'restrict_manage_posts', 'my_filter_list' );
function my_filter_list() {
$screen = get_current_screen();
global $wp_query;
if ( $screen->post_type == 'nm_portfolio' ) {
wp_dropdown_categories( array(
'show_option_all' => 'Show All Movie Genres',
'taxonomy' => 'movie_reviews_movie_genre',
'name' => 'movie_reviews_movie_genre',
'orderby' => 'name',
'selected' => ( isset( $wp_query->query['movie_reviews_movie_genre'] ) ? $wp_query->query['movie_reviews_movie_genre'] : '' ),
'hierarchical' => false,
'depth' => 3,
'show_count' => false,
'hide_empty' => true,
) );
}
}
add_filter( 'parse_query','perform_filtering' );
function perform_filtering( $query ) {
$qv = &$query->query_vars;
if ( ( $qv['movie_reviews_movie_genre'] ) && is_numeric( $qv['movie_reviews_movie_genre'] ) ) {
$term = get_term_by( 'id', $qv['movie_reviews_movie_genre'], 'movie_reviews_movie_genre' );
$qv['movie_reviews_movie_genre'] = $term->slug;
}
}
}
// Adding Taxonomies
add_action( 'init', 'create_my_taxonomies', 0 );
function create_my_taxonomies() {
register_taxonomy(
'nm_portfolio_service_type',
'nm_portfolio',
array(
'labels' => array(
'name' => 'Services Performed',
'add_new_item' => 'Add New Service',
'new_item_name' => "New Service Type"
),
'show_ui' => true,
'show_tagcloud' => false,
'hierarchical' => true
)
);
register_taxonomy(
'nm_portfolio_programs_used',
'nm_portfolio',
array(
'labels' => array(
'name' => 'Programs Used',
'add_new_item' => 'Add New Program',
'new_item_name' => "New Program"
),
'show_ui' => true,
'show_tagcloud' => false,
'hierarchical' => true
)
);
register_taxonomy(
'nm_portfolio_equipment_used',
'nm_portfolio',
array(
'labels' => array(
'name' => 'Equipment Used',
'add_new_item' => 'Add New Equipment',
'new_item_name' => "New Equipment"
),
'show_ui' => true,
'show_tagcloud' => false,
'hierarchical' => true
)
);
}
?>

I took out some parts but narrowed it down to this section below that was causing the problem.
// Custom Template Dedicated to Custom Post Types
add_filter( 'template_include','include_template_function', 1 );
function include_template_function( $template_path ) {
if ( get_post_type() == 'nm_portfolio' ) {
if ( is_single() ) {
// checks if the file exists in the theme first,
// otherwise serve the file from the plugin
if ( $theme_file = locate_template( array ( 'single-nm_portfolio.php' ) ) ) {
$template_path = $theme_file;
} else {
$template_path = plugin_dir_path( __FILE__ ) . '/single-nm_portfolio.php';
}
}
elseif ( is_archive() ) {
if ( $theme_file = locate_template( array ( 'archive-nm_portfolio.php' ) ) ) {
$template_path = $theme_file;
} else { $template_path = plugin_dir_path( __FILE__ ) . '/archive-nm_portfolio.php';
}
}
return $template_path;
}
I deleted add_filter( 'template_include','include_template_function', 1 ); and it seems to work fine now.
Below is my code all together that works and has been edited to get rid of a few things that I didn't really want anyway.
<?php
/*
Plugin Name: NM Portfolio
Plugin URI: http://work.nickmoyer.net
Description: Declares a plugin that will create a custom post type displaying movie reviews.
Version: 1.3
Author: Nick Moyer
Author URI: http://work.nickmoyer.net
License: GPLv2
*/
// Create a Custom Post Type
add_action( 'init', 'create_nm_portfolio' );
function create_nm_portfolio() {
register_post_type( 'nm_portfolio',
array(
'labels' => array(
'name' => 'NM Portfolio',
'singular_name' => 'NM Portfolio',
'add_new' => 'Add New',
'add_new_item' => 'Add New Portfolio Project',
'edit' => 'Edit',
'edit_item' => 'Edit Portfolio Project',
'new_item' => 'New Portfolio Project',
'view' => 'View',
'view_item' => 'View Portfolio Project',
'search_items' => 'Search Portfolio Projects',
'not_found' => 'No Portfolio Projects found',
'not_found_in_trash' =>
'No Portfolio Projects found in Trash',
'parent' => 'Parent Portfolio Project'
),
'public' => true,
'menu_position' => 15,
'supports' =>
array( 'title', 'editor', 'thumbnail' ),
'rewrite' => array('slug' => 'portfolio'),
'taxonomies' => array( '' ),
'has_archive' => true
)
);
}
// Creating Meta Box Fields for Custom Post Types
add_action( 'admin_init', 'my_admin' );
function my_admin() {
add_meta_box( 'nm_portfolio_cleint_meta_box','Portfolio Project Client Info','display_nm_portfolio_client_meta_box','nm_portfolio', 'normal', 'high' );
}
function display_nm_portfolio_client_meta_box( $nm_portfolio ) {
// Retrieve current name of the Director and Movie Rating based on review ID
$nm_clients = esc_html( get_post_meta( $nm_portfolio->ID,'nm_clients', true ) );
?>
<table>
<tr>
<td style="width: 100%">Client Name</td>
<td>
<input type="text" size="80" name="nm_portfolio_clients" value="<?php echo $nm_clients; ?>" />
</td>
</tr>
</table>
<?php }
add_action( 'save_post','add_nm_portfolio_fields', 10, 2 );
function add_nm_portfolio_fields( $nm_portfolio_id,$nm_portfolio ) {
// Check post type for movie reviews
if ( $nm_portfolio->post_type == 'nm_portfolio' ) {
// Store data in post meta table if present in post data
if ( isset( $_POST['nm_portfolio_clients'] ) && $_POST['nm_portfolio_clients'] != '' ) {
update_post_meta( $nm_portfolio_id, 'nm_clients', $_POST['nm_portfolio_clients'] );
}
}
}
// Custom Template Dedicated to Custom Post Types
function include_template_function( $template_path ) {
if ( get_post_type() == 'nm_portfolio' ) {
if ( is_single() ) {
// checks if the file exists in the theme first,
// otherwise serve the file from the plugin
if ( $theme_file = locate_template( array ( 'single-nm_portfolio.php' ) ) ) {
$template_path = $theme_file;
} else {
$template_path = plugin_dir_path( __FILE__ ) . '/single-nm_portfolio.php';
}
}
elseif ( is_archive() ) {
if ( $theme_file = locate_template( array ( 'archive-nm_portfolio.php' ) ) ) {
$template_path = $theme_file;
} else { $template_path = plugin_dir_path( __FILE__ ) . '/archive-nm_portfolio.php';
}
}
}
return $template_path;
}
// Adding Taxonomies
add_action( 'init', 'create_my_taxonomies', 0 );
function create_my_taxonomies() {
register_taxonomy(
'nm_portfolio_service_type',
'nm_portfolio',
array(
'labels' => array(
'name' => 'Services Performed',
'add_new_item' => 'Add New Service',
'new_item_name' => "New Service Type"
),
'show_ui' => true,
'show_tagcloud' => false,
'hierarchical' => true
)
);
register_taxonomy(
'nm_portfolio_programs_used',
'nm_portfolio',
array(
'labels' => array(
'name' => 'Programs Used',
'add_new_item' => 'Add New Program',
'new_item_name' => "New Program"
),
'show_ui' => true,
'show_tagcloud' => false,
'hierarchical' => true
)
);
register_taxonomy(
'nm_portfolio_equipment_used',
'nm_portfolio',
array(
'labels' => array(
'name' => 'Equipment Used',
'add_new_item' => 'Add New Equipment',
'new_item_name' => "New Equipment"
),
'show_ui' => true,
'show_tagcloud' => false,
'hierarchical' => true
)
);
}
?>
Thanks for your help!

There is no 'column_ordering' function defined, though it is necessary for «add_filter( 'request', 'column_ordering' );»
Kill this filter out from code and hapiness will come!

Related

Can't add a section to a Woocommerce Custom Setting Tab [duplicate]

I'm trying to add a custom settings tab to the WooCommerce settings screen. Basically I want to achieve a similar thing to the Products settings tab, with the subsections/subtabs:
I haven't been able to find any decent documentation on how to do this but I've been able to add a custom tab using this snippet:
class WC_Settings_Tab_Demo {
public static function init() {
add_filter( 'woocommerce_settings_tabs_array', __CLASS__ . '::add_settings_tab', 50 );
}
public static function add_settings_tab( $settings_tabs ) {
$settings_tabs['test'] = __( 'Settings Demo Tab', 'woocommerce-settings-tab-demo' );
return $settings_tabs;
}
}
WC_Settings_Tab_Demo::init();
Based on what I've dug up from various threads/tutorials, I've been trying to add the sections/subtabs to the new settings tab something like this:
// creating a new sub tab in API settings
add_filter( 'woocommerce_get_sections_test','add_subtab' );
function add_subtab( $sections ) {
$sections['custom_settings'] = __( 'Custom Settings', 'woocommerce-custom-settings-tab' );
$sections['more_settings'] = __( 'More Settings', 'woocommerce-custom-settings-tab' );
return $sections;
}
// adding settings (HTML Form)
add_filter( 'woocommerce_get_settings_test', 'add_subtab_settings', 10, 2 );
function add_subtab_settings( $settings, $current_section ) {
// $current_section = (isset($_GET['section']) && !empty($_GET['section']))? $_GET['section']:'';
if ( $current_section == 'custom_settings' ) {
$custom_settings = array();
$custom_settings[] = array( 'name' => __( 'Custom Settings', 'text-domain' ),
'type' => 'title',
'desc' => __( 'The following options are used to ...', 'text-domain' ),
'id' => 'custom_settings'
);
$custom_settings[] = array(
'name' => __( 'Field 1', 'text-domain' ),
'id' => 'field_one',
'type' => 'text',
'default' => get_option('field_one'),
);
$custom_settings[] = array( 'type' => 'sectionend', 'id' => 'test-options' );
return $custom_settings;
} else {
// If not, return the standard settings
return $settings;
}
}
I've been able to add new subsections to the Products tab using similar code to the above, but it isn't working for my new custom tab. Where am I going wrong here?
1) To add a setting tab with sections, you can firstly use the woocommerce_settings_tabs_array filter hook:
// Add the tab to the tabs array
function filter_woocommerce_settings_tabs_array( $settings_tabs ) {
$settings_tabs['my-custom-tab'] = __( 'My custom tab', 'woocommerce' );
return $settings_tabs;
}
add_filter( 'woocommerce_settings_tabs_array', 'filter_woocommerce_settings_tabs_array', 99 );
2) To add new sections to the page, you can use the woocommerce_sections_{$current_tab} composite hook where {$current_tab} need to be replaced by the key slug that is set in the first function:
// Add new sections to the page
function action_woocommerce_sections_my_custom_tab() {
global $current_section;
$tab_id = 'my-custom-tab';
// Must contain more than one section to display the links
// Make first element's key empty ('')
$sections = array(
'' => __( 'Overview', 'woocommerce' ),
'my-section-1' => __( 'My section 1', 'woocommerce' ),
'my-section-2' => __( 'My section 2', 'woocommerce' )
);
echo '<ul class="subsubsub">';
$array_keys = array_keys( $sections );
foreach ( $sections as $id => $label ) {
echo '<li>' . $label . ' ' . ( end( $array_keys ) == $id ? '' : '|' ) . ' </li>';
}
echo '</ul><br class="clear" />';
}
add_action( 'woocommerce_sections_my-custom-tab', 'action_woocommerce_sections_my_custom_tab', 10 );
3) For adding the settings, as well as for processing/saving, we will use a custom function, which we will then call:
// Settings function
function get_custom_settings() {
global $current_section;
$settings = array();
if ( $current_section == 'my-section-1' ) {
// My section 1
$settings = array(
// Title
array(
'title' => __( 'Your title 1', 'woocommerce' ),
'type' => 'title',
'id' => 'custom_settings_1'
),
// Text
array(
'title' => __( 'Your title 1.1', 'text-domain' ),
'type' => 'text',
'desc' => __( 'Your description 1.1', 'woocommerce' ),
'desc_tip' => true,
'id' => 'custom_settings_1_text',
'css' => 'min-width:300px;'
),
// Select
array(
'title' => __( 'Your title 1.2', 'woocommerce' ),
'desc' => __( 'Your description 1.2', 'woocommerce' ),
'id' => 'custom_settings_1_select',
'class' => 'wc-enhanced-select',
'css' => 'min-width:300px;',
'default' => 'aa',
'type' => 'select',
'options' => array(
'aa' => __( 'aa', 'woocommerce' ),
'bb' => __( 'bb', 'woocommerce' ),
'cc' => __( 'cc', 'woocommerce' ),
'dd' => __( 'dd', 'woocommerce' ),
),
'desc_tip' => true,
),
// Section end
array(
'type' => 'sectionend',
'id' => 'custom_settings_1'
),
);
} elseif ( $current_section == 'my-section-2' ) {
// My section 2
$settings = array(
// Title
array(
'title' => __( 'Your title 2', 'woocommerce' ),
'type' => 'title',
'id' => 'custom_settings_2'
),
// Text
array(
'title' => __( 'Your title 2.2', 'text-domain' ),
'type' => 'text',
'desc' => __( 'Your description 2.1', 'woocommerce' ),
'desc_tip' => true,
'id' => 'custom_settings_2_text',
'css' => 'min-width:300px;'
),
// Section end
array(
'type' => 'sectionend',
'id' => 'custom_settings_2'
),
);
} else {
// Overview
$settings = array(
// Title
array(
'title' => __( 'Overview', 'woocommerce' ),
'type' => 'title',
'id' => 'custom_settings_overview'
),
// Section end
array(
'type' => 'sectionend',
'id' => 'custom_settings_overview'
),
);
}
return $settings;
}
3.1) Add settings, via the woocommerce_settings_{$current_tab} composite hook:
// Add settings
function action_woocommerce_settings_my_custom_tab() {
// Call settings function
$settings = get_custom_settings();
WC_Admin_Settings::output_fields( $settings );
}
add_action( 'woocommerce_settings_my-custom-tab', 'action_woocommerce_settings_my_custom_tab', 10 );
3.2) Process/save the settings, via the woocommerce_settings_save_{$current_tab} composite hook:
// Process/save the settings
function action_woocommerce_settings_save_my_custom_tab() {
global $current_section;
$tab_id = 'my-custom-tab';
// Call settings function
$settings = get_custom_settings();
WC_Admin_Settings::save_fields( $settings );
if ( $current_section ) {
do_action( 'woocommerce_update_options_' . $tab_id . '_' . $current_section );
}
}
add_action( 'woocommerce_settings_save_my-custom-tab', 'action_woocommerce_settings_save_my_custom_tab', 10 );
Result:
Based on:
Implement a custom WooCommerce settings page, including page sections
woocommerce/includes/admin/settings/

Custom post type taxonomy not being replaced in ACF post object field output

I have a custom post type (Photos) and a taxonomy (Locations) setup on my client's website. The permalinks work correctly when accessed using the menus, search, and directly from the custom post type in the WordPress admin panel, but not when accessing them using an Advanced Custom Fields post object field in my Timber/Twig template. The taxonomy portion (%locations%) of the URL is not being replaced. For example, http://example.com/photos/`%locations%`/taj-mahal-and-the-ganges/. The %locations% should be replaced with world and india, which are locations from the custom taxonomy.
The post's custom post object field is being pulled into the template using the following code: {{ __('View photo gallery', textdomain) }}.
I have included my custom post type and taxonomy code below:
function textdomain_register_photos_post_type() {
$args = [
'label' => 'Photo Galleries',
'labels' => [
'singular_name' => _x( 'Photo Gallery', 'singular' ),
'menu_name' => _x( 'Photo Galleries', 'admin menu' ),
'name_admin_bar' => _x( 'Photo Galleries', 'admin bar' ),
'add_new' => _x( 'Add New', 'add new' ),
'add_new_item' => __( 'Add New Photo Gallery' ),
'new_item' => __( 'New Photo Gallery' ),
'edit_item' => __( 'Edit Photo Gallery' ),
'view_item' => __( 'View Photo Gallery' ),
'all_items' => __( 'All Photo Galleries' ),
'search_items' => __( 'Search Photo Galleries' ),
'not_found' => __( 'No photo galleries found.' ),
],
'supports' => array(
'title',
'editor',
'thumbnail'
),
'public' => true,
'menu_position' => 5,
'menu_icon' => 'dashicons-format-gallery',
'capability_type' => 'post',
'taxonomies' => [ 'locations', ],
'has_archive' => true,
'delete_with_user' => false,
'rewrite' => [
'slug' => 'photos/%locations%',
'with_front' => false,
],
];
register_post_type( 'photos', $args );
};
add_action( 'init', 'textdomain_register_photos_post_type' );
function textdomain_register_locations_taxonomy() {
$args = [
'labels' => [
'name' => _x( 'Locations', 'taxonomy general name' ),
'singular_name' => _x( 'Location', 'taxonomy singular name' ),
'search_items' => __( 'Search Locations' ),
'all_items' => __( 'All Locations' ),
'parent_item' => __( 'Parent Location' ),
'parent_item_colon' => __( 'Parent Location:' ),
'edit_item' => __( 'Edit Location' ),
'update_item' => __( 'Update Location' ),
'add_new_item' => __( 'Add New Location' ),
'new_item_name' => __( 'New Location Name' ),
'menu_name' => __( 'Locations' ),
],
'hierarchical' => true,
'rewrite' => [
'slug' => 'locations',
'hierarchical' => true,
],
];
register_taxonomy( 'locations', [ 'photos' ], $args );
};
add_action( 'init', 'textdomain_register_locations_taxonomy' );
add_filter( 'post_type_link', 'textdomain_post_type_link', 10, 2 );
function textdomain_post_type_link( $post_link, $post ) {
// Bail out if not photos post type.
if ( 'photos' !== $post->post_type ) {
return $post_link;
}
$taxonomy = 'locations';
$terms = get_the_terms( get_the_ID(), $taxonomy );
$slug = [];
foreach ( $terms as $term ) {
if ( $term->parent == 0 ) {
array_unshift( $slug, sanitize_title_with_dashes( $term->name ) );
} else {
array_push( $slug, sanitize_title_with_dashes( $term->name ) );
}
}
if ( ! empty( $slug ) ) {
$post_link = str_replace( '%' . $taxonomy . '%', join( '/', $slug ), $post_link );
}
return $post_link;
}
I have saved my permalinks multiple times and have flush_rewrite_rules(); at the bottom of my theme's functions file.
Update
WordPress is displaying this warning Invalid argument supplied foreach() on line 422 of the functions.php file. The code is as follows:
$taxonomy = 'locations';
$terms = get_the_terms( get_the_ID(), $taxonomy );
$slug = [];
foreach ( $terms as $term ) {
if ( $term->parent == 0 ) {
array_unshift( $slug, sanitize_title_with_dashes( $term->name ) );
} else {
array_push( $slug, sanitize_title_with_dashes( $term->name ) );
}
}
I am not sure if this could be causing the issue, but my PHP knowledge is limited.
Any tips or suggestions on this issue are greatly appreciated.
I figured out the issue was related to how the post ID was being retrieved for the taxonomies. I reviewed the get_the_terms function reference and found that get_the_ID() needed to be replaced by $post->ID in the following line: $terms = get_the_terms( $post->ID, $taxonomy );. My updated and working function is below.
add_filter( 'post_type_link', 'textdomain_post_type_link', 10, 2 );
function textdomain_post_type_link( $post_link, $post ) {
// Bail out if not photos post type.
if ( 'photos' !== $post->post_type ) {
return $post_link;
}
$taxonomy = 'locations';
// Replaced get_the_ID() with $post->ID
$terms = get_the_terms( $post->ID, $taxonomy );
$slug = [];
foreach ( $terms as $term ) {
if ( $term->parent == 0 ) {
array_unshift( $slug, sanitize_title_with_dashes( $term->name ) );
} else {
array_push( $slug, sanitize_title_with_dashes( $term->name ) );
}
}
if ( ! empty( $slug ) ) {
$post_link = str_replace( '%' . $taxonomy . '%', join( '/', $slug ), $post_link );
}
return $post_link;
}

Custom post meta showing on localhost, but not live server?

I'm having an issue and, honestly, I have absolutely no idea what's going on...
I have some custom meta fields for my custom post type (called review). On my local installation, they appear and work perfectly:
However, on live, they don't show up! Completely vanished!
The panel is selected in Screen Options too, so that's not the issue:
Here is the code for my entire custom post type... perhaps I've done something stupid?
<?php
// Register Custom Post Type
function review() {
$labels = array(
'name' => 'Reviews',
'singular_name' => 'Review',
'menu_name' => 'Reviews',
'name_admin_bar' => 'Review',
'archives' => 'Review Archives',
'parent_item_colon' => 'Parent Item:',
'all_items' => 'All Items',
'add_new_item' => 'Add New Item',
'add_new' => 'Add New',
'new_item' => 'New Item',
'edit_item' => 'Edit Item',
'update_item' => 'Update Item',
'view_item' => 'View Item',
'search_items' => 'Search Item',
'not_found' => 'Not found',
'not_found_in_trash' => 'Not found in Trash',
'featured_image' => 'Featured Image',
'set_featured_image' => 'Set featured image',
'remove_featured_image' => 'Remove featured image',
'use_featured_image' => 'Use as featured image',
'insert_into_item' => 'Insert into item',
'uploaded_to_this_item' => 'Uploaded to this item',
'items_list' => 'Items list',
'items_list_navigation' => 'Items list navigation',
'filter_items_list' => 'Filter items list',
);
$args = array(
'label' => 'Review',
'description' => 'A product review',
'labels' => $labels,
'supports' => array( 'title', 'editor', 'excerpt', 'author', 'thumbnail', 'comments', 'revisions'),
'taxonomies' => array( 'category', 'post_tag' ),
'hierarchical' => false,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'menu_position' => 5,
'menu_icon' => 'dashicons-edit',
'show_in_admin_bar' => true,
'show_in_nav_menus' => true,
'can_export' => true,
'has_archive' => true,
'exclude_from_search' => false,
'publicly_queryable' => true,
'capability_type' => 'page',
);
register_post_type( 'review', $args );
}
add_action( 'init', 'review', 0 );
//Review options meta
/**
* Generated by the WordPress Meta Box generator
* at http://jeremyhixon.com/tool/wordpress-meta-box-generator/
*/
function review_options_get_meta( $value ) {
global $post;
$field = get_post_meta( $post->ID, $value, true );
if ( ! empty( $field ) ) {
return is_array( $field ) ? stripslashes_deep( $field ) : stripslashes( wp_kses_decode_entities( $field ) );
} else {
return false;
}
}
function review_options_add_meta_box() {
add_meta_box(
'review_options-review-options',
__( 'Review options', 'review_options' ),
'review_options_html',
'review',
'core',
'high'
);
}
add_action( 'add_meta_boxes', 'review_options_add_meta_box' );
function review_options_html( $post) {
wp_nonce_field( '_review_options_nonce', 'review_options_nonce' ); ?>
<p>Options for your reviews</p>
<p>
<label for="review_options_review_score"><?php _e( 'Review Score', 'review_options' ); ?></label><br>
<select name="review_options_review_score" id="review_options_review_score" style="width: 50%;">
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '1' ) ? 'selected' : '' ?>>1</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '2' ) ? 'selected' : '' ?>>2</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '3' ) ? 'selected' : '' ?>>3</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '4' ) ? 'selected' : '' ?>>4</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '5' ) ? 'selected' : '' ?>>5</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '6' ) ? 'selected' : '' ?>>6</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '7' ) ? 'selected' : '' ?>>7</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '8' ) ? 'selected' : '' ?>>8</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '9' ) ? 'selected' : '' ?>>9</option>
<option <?php echo (review_options_get_meta( 'review_options_review_score' ) === '10' ) ? 'selected' : '' ?>>10</option>
</select>
</p> <p>
<label for="review_options_review_title_colour"><?php _e( 'Review title colour', 'review_options' ); ?></label><br>
<select name="review_options_review_title_colour" id="review_options_review_title_colour">
<option <?php echo (review_options_get_meta( 'review_options_review_title_colour' ) === '' ) ? 'selected' : '' ?>>Default</option>
<option <?php echo (review_options_get_meta( 'review_options_review_title_colour' ) === 'black' ) ? 'selected' : '' ?>>Black</option>
<option <?php echo (review_options_get_meta( 'review_options_review_title_colour' ) === 'white' ) ? 'selected' : '' ?>>White</option>
</select>
</p><?php
}
function review_options_save( $post_id ) {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( ! isset( $_POST['review_options_nonce'] ) || ! wp_verify_nonce( $_POST['review_options_nonce'], '_review_options_nonce' ) ) return;
if ( ! current_user_can( 'edit_post', $post_id ) ) return;
if ( isset( $_POST['review_options_review_score'] ) )
update_post_meta( $post_id, 'review_options_review_score', esc_attr( $_POST['review_options_review_score'] ) );
if ( isset( $_POST['review_options_review_title_colour'] ) )
update_post_meta( $post_id, 'review_options_review_title_colour', esc_attr( $_POST['review_options_review_title_colour'] ) );
}
add_action( 'save_post', 'review_options_save' );
/*
Usage: review_options_get_meta( 'review_options_review_score' )
Usage: review_options_get_meta( 'review_options_review_title_colour' )
*/
?>
Or perhaps it's something to do with my only other post type?
<?php // Register Custom Post Type
function product() {
$labels = array(
'name' => _x( 'Products', 'Post Type General Name', 'text_domain' ),
'singular_name' => _x( 'Product', 'Post Type Singular Name', 'text_domain' ),
'menu_name' => __( 'Product', 'text_domain' ),
'name_admin_bar' => __( 'Product', 'text_domain' ),
'archives' => __( 'Products', 'text_domain' ),
'parent_item_colon' => __( 'Product', 'text_domain' ),
'all_items' => __( 'All Products', 'text_domain' ),
'add_new_item' => __( 'Add New Product', 'text_domain' ),
'add_new' => __( 'Add New', 'text_domain' ),
'new_item' => __( 'New Product', 'text_domain' ),
'edit_item' => __( 'Edit Product', 'text_domain' ),
'update_item' => __( 'Update Product', 'text_domain' ),
'view_item' => __( 'View Product', 'text_domain' ),
'search_items' => __( 'Search Products', 'text_domain' ),
'not_found' => __( 'Not found', 'text_domain' ),
'not_found_in_trash' => __( 'Not found in Trash', 'text_domain' ),
'featured_image' => __( 'Featured Image', 'text_domain' ),
'set_featured_image' => __( 'Set featured image', 'text_domain' ),
'remove_featured_image' => __( 'Remove featured image', 'text_domain' ),
'use_featured_image' => __( 'Use as featured image', 'text_domain' ),
'insert_into_item' => __( 'Insert into Product', 'text_domain' ),
'uploaded_to_this_item' => __( 'Uploaded to this Product', 'text_domain' ),
'items_list' => __( 'Product list', 'text_domain' ),
'items_list_navigation' => __( 'Product list navigation', 'text_domain' ),
'filter_items_list' => __( 'Filter Product list', 'text_domain' ),
);
$args = array(
'label' => __( 'Product', 'text_domain' ),
'description' => __( 'A product', 'text_domain' ),
'labels' => $labels,
'supports' => array( 'title', 'editor', 'thumbnail', ),
'hierarchical' => false,
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'menu_position' => 8,
'menu_icon' => 'dashicons-archive',
'show_in_admin_bar' => true,
'show_in_nav_menus' => true,
'can_export' => true,
'has_archive' => true,
'exclude_from_search' => true,
'publicly_queryable' => true,
'capability_type' => 'page',
);
register_post_type( 'product', $args );
}
add_action( 'init', 'product', 0 );
//Creation of Meta Box for post type "destination_category" (Start)
add_action( 'admin_init', 'my_destination_category' );
//destination_sub_category_admin - is the required HTML id attribute
//Select Destination Sub Category - is the text visible in the heading of the meta box section
//display_destination_subcategory_meta_box - is the callback which renders the contents of the meta box
//destination_category - is the name of the custom post type where the meta box will be displayed
// normal - defines the part of the page where the edit screen section should be shown
// high - defines the priority within the context where the boxes should show
function my_destination_category() {
foreach( array( 'post', 'review' ) as $pt )
add_meta_box(
'destination_sub_category_admin',
'Select Destination Sub Category',
'display_destination_subcategory_meta_box',
$pt,
'normal',
'high');
function display_destination_subcategory_meta_box( $select_category ) {
// Retrieve Current Selected Category ID based on the Category Created
global $wpdb;
$selectcat="SELECT * FROM ".$wpdb->prefix."posts WHERE `post_type`='product' AND `post_status`='publish' ORDER BY `ID` DESC";
$resultant = $wpdb->get_results($selectcat);
$rescount=count($resultant);
$category_selected_id = intval( get_post_meta( $select_category->ID, 'destination_category_id', true ) );
?>
<table>
<tr>
<td style="width: 150px">Select Category</td>
<td>
<select style="width: 100px" name="category_selection" id="meta_box_category" style="float:left; width:50%; !important">
<?php
if($rescount==0)
{?>
<option value="null">No Posts have been created</option>
<?php
}
else
{
// Generate all items of drop-down list
?>
<option value="">None</option>
<?php
foreach($resultant as $singleresultant)
{
?>
<option value="<?php echo $singleresultant->ID; ?>" <?php echo selected( $singleresultant->ID, $category_selected_id ); ?>>
<?php echo $singleresultant->post_title; ?>
</option>
<?php
}
}
?>
</select>
</td>
</tr>
</table>
<?php
}
// Registering a Save Post Function
add_action( 'save_post', 'destination_admin_sub_category', 10, 2 );
function destination_admin_sub_category( $select_category_id, $select_category ) {
if ( $select_category->post_type == 'post' || 'review' ) {
if ( isset( $_POST['category_selection'] ) && $_POST['category_selection'] != '' ) {
echo update_post_meta( $select_category_id, 'destination_category_id', $_POST['category_selection'] );
} }
}
}
/**
* Generated by the WordPress Meta Box Generator at
*/
class Rational_Meta_Box {
private $screens = array(
'product',
);
private $fields = array(
array(
'id' => 'box-art',
'label' => 'Box Art',
'type' => 'media',
),
array(
'id' => 'developer',
'label' => 'Developer',
'type' => 'text',
),
array(
'id' => 'publisher',
'label' => 'Publisher',
'type' => 'text',
),
array(
'id' => 'release-date',
'label' => 'Release Date',
'type' => 'date',
),
);
/**
* Class construct method. Adds actions to their respective WordPress hooks.
*/
public function __construct() {
add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );
add_action( 'admin_footer', array( $this, 'admin_footer' ) );
add_action( 'save_post', array( $this, 'save_post' ) );
}
/**
* Hooks into WordPress' add_meta_boxes function.
* Goes through screens (post types) and adds the meta box.
*/
public function add_meta_boxes() {
foreach ( $this->screens as $screen ) {
add_meta_box(
'product-options',
__( 'Product Options', 'product-options' ),
array( $this, 'add_meta_box_callback' ),
$screen,
'advanced',
'core'
);
}
}
/**
* Generates the HTML for the meta box
*
* #param object $post WordPress post object
*/
public function add_meta_box_callback( $post ) {
wp_nonce_field( 'product_options_data', 'product_options_nonce' );
echo 'Options for products';
$this->generate_fields( $post );
}
/**
* Hooks into WordPress' admin_footer function.
* Adds scripts for media uploader.
*/
public function admin_footer() {
?><script>
// https://codestag.com/how-to-use-wordpress-3-5-media-uploader-in-theme-options/
jQuery(document).ready(function($){
if ( typeof wp.media !== 'undefined' ) {
var _custom_media = true,
_orig_send_attachment = wp.media.editor.send.attachment;
$('.rational-metabox-media').click(function(e) {
var send_attachment_bkp = wp.media.editor.send.attachment;
var button = $(this);
var id = button.attr('id').replace('_button', '');
_custom_media = true;
wp.media.editor.send.attachment = function(props, attachment){
if ( _custom_media ) {
$("#"+id).val(attachment.url);
} else {
return _orig_send_attachment.apply( this, [props, attachment] );
};
}
wp.media.editor.open(button);
return false;
});
$('.add_media').on('click', function(){
_custom_media = false;
});
}
});
</script><?php
}
/**
* Generates the field's HTML for the meta box.
*/
public function generate_fields( $post ) {
$output = '';
foreach ( $this->fields as $field ) {
$label = '<label for="' . $field['id'] . '">' . $field['label'] . '</label>';
$db_value = get_post_meta( $post->ID, 'product_options_' . $field['id'], true );
switch ( $field['type'] ) {
case 'media':
$input = sprintf(
'<input class="regular-text" id="%s" name="%s" type="text" value="%s"> <input class="button rational-metabox-media" id="%s_button" name="%s_button" type="button" value="Upload" />',
$field['id'],
$field['id'],
$db_value,
$field['id'],
$field['id']
);
break;
default:
$input = sprintf(
'<input %s id="%s" name="%s" type="%s" value="%s">',
$field['type'] !== 'color' ? 'class="regular-text"' : '',
$field['id'],
$field['id'],
$field['type'],
$db_value
);
}
$output .= $this->row_format( $label, $input );
}
echo '<table class="form-table"><tbody>' . $output . '</tbody></table>';
}
/**
* Generates the HTML for table rows.
*/
public function row_format( $label, $input ) {
return sprintf(
'<tr><th scope="row">%s</th><td>%s</td></tr>',
$label,
$input
);
}
/**
* Hooks into WordPress' save_post function
*/
public function save_post( $post_id ) {
if ( ! isset( $_POST['product_options_nonce'] ) )
return $post_id;
$nonce = $_POST['product_options_nonce'];
if ( !wp_verify_nonce( $nonce, 'product_options_data' ) )
return $post_id;
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return $post_id;
foreach ( $this->fields as $field ) {
if ( isset( $_POST[ $field['id'] ] ) ) {
switch ( $field['type'] ) {
case 'email':
$_POST[ $field['id'] ] = sanitize_email( $_POST[ $field['id'] ] );
break;
case 'text':
$_POST[ $field['id'] ] = sanitize_text_field( $_POST[ $field['id'] ] );
break;
}
update_post_meta( $post_id, 'product_options_' . $field['id'], $_POST[ $field['id'] ] );
} else if ( $field['type'] === 'checkbox' ) {
update_post_meta( $post_id, 'product_options_' . $field['id'], '0' );
}
}
}
}
new Rational_Meta_Box;
?>
Either way, I have absolutely no idea why it's working perfectly locally and messing up on my live server... it's baffling!
Thanks in advance for your help!

WordPress Taxonomy Term meta not working with export and import

I have created a Taxonomy Meta Data for Custom Post Type and its working fine while saving, updating, editing etc. But its not working while importing or exporting with wordpress importer. Taxonomies meta data are not importing.
Here is the Code based on the Tutorial
<?php
if ( ! function_exists( 'register_cpt_houses' ) ) {
function register_cpt_houses() {
$labels = array(
'name' => __('houses', 'my_plugin'),
'singular_name' => __('houses', 'my_plugin'),
'add_new' => __('Add New','my_plugin'),
'add_new_item' => __('Add New Slide','my_plugin'),
'edit_item' => __('Edit houses','my_plugin'),
'new_item' => __('New houses','my_plugin'),
'view_item' => __('View houses','my_plugin'),
'search_items' => __('Search houses','my_plugin'),
'not_found' => __('No houses found','my_plugin'),
'not_found_in_trash'=> __('No houses found in Trash','my_plugin'),
'parent_item_colon' => '' ,
'all_items' => __( 'All houses' ,'my_plugin')
);
$args = array(
'labels' => $labels,
'public' => true,
'exclude_from_search'=> false,
'show_ui' => true,
'capability_type' => 'post',
'hierarchical' => false,
'rewrite' => array('slug'=>'houses', 'with_front' => true ),
'query_var' => false,
'menu_position' => null,
'supports' => array('title', 'thumbnail', 'page-attributes')
);
register_post_type('houses',$args);
}
add_action('init', 'register_cpt_houses');
}
function register_feature_taxonomy() {
$labels = array(
'name' => _x( 'Features', 'taxonomy general name', 'my_plugin' ),
'singular_name' => _x('Features', 'taxonomy singular name', 'my_plugin'),
'search_items' => __('Search Feature', 'my_plugin'),
'popular_items' => __('Common Features', 'my_plugin'),
'all_items' => __('All Features', 'my_plugin'),
'edit_item' => __('Edit Feature', 'my_plugin'),
'update_item' => __('Update Feature', 'my_plugin'),
'add_new_item' => __('Add new Feature', 'my_plugin'),
'new_item_name' => __('New Feature:', 'my_plugin'),
'add_or_remove_items' => __('Remove Feature', 'my_plugin'),
'choose_from_most_used' => __('Choose from common Feature', 'my_plugin'),
'not_found' => __('No Feature found.', 'my_plugin'),
'menu_name' => __('Features', 'my_plugin'),
);
$args = array(
'hierarchical' => false,
'labels' => $labels,
'show_ui' => true,
);
register_taxonomy('house_feature','houses', $args);
}
add_action( 'house_feature_add_form_fields', 'add_feature_group_field', 10, 2 );
function add_feature_group_field($taxonomy) {
global $feature_groups;
?><div class="form-field term-group">
<label for="featuret-group"><?php _e('Feature Group', 'my_plugin'); ?></label>
<select class="postform" id="equipment-group" name="feature-group">
<option value="-1"><?php _e('none', 'my_plugin'); ?></option><?php foreach ($feature_groups as $_group_key => $_group) : ?>
<option value="<?php echo $_group_key; ?>" class=""><?php echo $_group; ?></option>
<?php endforeach; ?>
</select>
</div><?php
}
add_action( 'created_house_feature', 'save_feature_meta', 10, 2 );
function save_feature_meta( $term_id, $tt_id ){
if( isset( $_POST['feature-group'] ) && '' !== $_POST['feature-group'] ){
$group = sanitize_title( $_POST['feature-group'] );
add_term_meta( $term_id, 'feature-group', $group, true );
}
}
add_action( 'house_feature_edit_form_fields', 'edit_feature_group_field', 10, 2 );
function edit_feature_group_field( $term, $taxonomy ){
global $feature_groups;
// get current group
$feature_group = get_term_meta( $term->term_id, 'feature-group', true );
?><tr class="form-field term-group-wrap">
<th scope="row"><label for="feature-group"><?php _e( 'Feature Group', 'my_plugin' ); ?></label></th>
<td><select class="postform" id="feature-group" name="feature-group">
<option value="-1"><?php _e( 'none', 'my_plugin' ); ?></option>
<?php foreach( $feature_groups as $_group_key => $_group ) : ?>
<option value="<?php echo $_group_key; ?>" <?php selected( $feature_group, $_group_key ); ?>><?php echo $_group; ?></option>
<?php endforeach; ?>
</select></td>
</tr><?php
}
add_action( 'edited_house_feature', 'update_feature_meta', 10, 2 );
function update_feature_meta( $term_id, $tt_id ){
if( isset( $_POST['feature-group'] ) && '' !== $_POST['feature-group'] ){
$group = sanitize_title( $_POST['feature-group'] );
update_term_meta( $term_id, 'feature-group', $group );
}
}
add_filter('manage_edit-house_feature_columns', 'add_feature_group_column' );
function add_feature_group_column( $columns ){
$columns['feature_group'] = __( 'Group', 'my_plugin' );
return $columns;
}
add_filter('manage_house_feature_custom_column', 'add_feature_group_column_content', 10, 3 );
function add_feature_group_column_content( $content, $column_name, $term_id ){
global $feature_groups;
if( $column_name !== 'feature_group' ){
return $content;
}
$term_id = absint( $term_id );
$feature_group = get_term_meta( $term_id, 'feature-group', true );
if( !empty( $feature_group ) ){
$content .= esc_attr( $feature_groups[ $feature_group ] );
}
return $content;
}
add_filter( 'manage_edit-house_feature_sortable_columns', 'add_feature_group_column_sortable' );
function add_feature_group_column_sortable( $sortable ){
$sortable[ 'feature_group' ] = 'feature_group';
return $sortable;
}
?>
What am I doing wrong?
If you need to export the data in termmeta table then try this plugin to export the termmeta data in separate XML file.
Export custom post type will only get you connection between the taxonomy ID and Post exported.
To get the Meta data of that taxonomy try this plugin It will provide you a XML containing all additional entries of that Taxonomy you can import that too
https://wordpress.org/plugins/wp-export-categories-taxonomies/
You will find this in Tools -> Wp Export Cats & Taxs
Select the Taxonomy in custom post types you want to export ..

Showing custom taxonomy column in custom posts type listings

I have created a custom post type named banners. Thereby I register a new taxonomy called location that specifies on which page the banner is to be shown. Everything is great however when I click on the custom posts type 'Banner' in the admin window I see all the banners created however the table does not have a column for the taxonomy 'Location'.
In other words I want to be able to see what location the banner is in, in the banners listing.
For those interested, the register_taxonomy register_taxonomy function, as of WordPress 3.5, now offers an argument for show_admin_column (false by default). Set to true, it automatically displays the taxonomy column in the admin.
You can use the manage_post-type_custom_column and manage_edit_post-type_columns filters to add your taxonomy column to the post type listing.
add_action( 'admin_init', 'my_admin_init' );
function my_admin_init() {
add_filter( 'manage_edit-banner_columns', 'my_new_custom_post_column');
add_action( 'manage_banner_custom_column', 'location_tax_column_info', 10, 2);
}
function my_new_custom_post_column( $column ) {
$column['location'] = 'Location';
return $column;
}
function location_tax_column_info( $column_name, $post_id ) {
$taxonomy = $column_name;
$post_type = get_post_type($post_id);
$terms = get_the_terms($post_id, $taxonomy);
if (!empty($terms) ) {
foreach ( $terms as $term )
$post_terms[] ="<a href='edit.php?post_type={$post_type}&{$taxonomy}={$term->slug}'> " .esc_html(sanitize_term_field('name', $term->name, $term->term_id, $taxonomy, 'edit')) . "</a>";
echo join('', $post_terms );
}
else echo '<i>No Location Set. </i>';
}
//what version of wordpress you are using
//since wp 3.5 you can pass parameter show_admin_column=>true
// hook into the init action and call create_book_taxonomies when it fires
add_action( 'init', 'create_book_taxonomies', 0 );
// create two taxonomies, genres and writers for the post type "book"
function create_book_taxonomies() {
// Add new taxonomy, make it hierarchical (like categories)
$labels = array(
'name' => _x( 'Genres', 'taxonomy general name' ),
'singular_name' => _x( 'Genre', 'taxonomy singular name' ),
'search_items' => __( 'Search Genres' ),
'all_items' => __( 'All Genres' ),
'parent_item' => __( 'Parent Genre' ),
'parent_item_colon' => __( 'Parent Genre:' ),
'edit_item' => __( 'Edit Genre' ),
'update_item' => __( 'Update Genre' ),
'add_new_item' => __( 'Add New Genre' ),
'new_item_name' => __( 'New Genre Name' ),
'menu_name' => __( 'Genre' ),
);
$args = array(
'hierarchical' => true,
'labels' => $labels,
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'genre' ),
);
register_taxonomy( 'genre', array( 'book' ), $args );
}
In addition to Jonathan Wold answer, you can add the ability to filter by your custom taxonomy like this:
add_action('restrict_manage_posts', 'filter_post_type_backend_by_taxonomies', 99, 2);
function filter_post_type_backend_by_taxonomies($post_type, $which) {
if( 'your_post_type' !== $post_type) {
return;
}
$taxonomies = array( 'your_custom_taxonomy' );
foreach( $taxonomies as $taxonomy_slug ) {
$taxonomy_obj = get_taxonomy( $taxonomy_slug );
$taxonomy_name = $taxonomy_obj->labels->name;
$terms = get_terms($taxonomy_slug);
echo "<select name='{$taxonomy_slug}' id='{$taxonomy_slug}' class='postform'>";
echo '<option value="">' . sprintf( esc_html__( 'Show all %s', 'domain-name' ), $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>';
}
}

Resources