How to add custom post type in Tab

show post types and settings in tabs

Add custom post type List Table in Tab Content

Add custom post type in tab to display all the settings, post types, and reports in one menu/submenu. This helps to add your plugin’s post types and settings in one place to help your customer find them and it is also very useful for a great customer experience. End users of your plugin or theme find and explore everything quickly and easily.

How to add custom post types in submenu

It is effortless to show any post type in a menu submenu. It is needed to assign the value of the slug of a menu in a parameter “show_in_menu”.https://developer.wordpress.org/plugins/post-types/registering-custom-post-types/
$labels = array(
	'name'                => esc_html__( '{Your Label}', '{your text domain}' ),
	'singular_name'       => esc_html__( '{Your Label}', '{your text domain}' ),
	'add_new'             => esc_html__( '{Your Label}', '{your text domain}' ),
	'add_new_item'        => esc_html__( '{Your Label}', '{your text domain}' ),
	'edit_item'           => esc_html__( '{Your Label}', '{your text domain}' ),
	'new_item'            => esc_html__( '{Your Label}', '{your text domain}' ),
	'view_item'           => esc_html__( '{Your Label}', '{your text domain}' ),
	'search_items'        => esc_html__( '{Your Label}', '{your text domain}' ),
	'not_found'           => esc_html__( '{Your Label}', '{your text domain}' ),
	'not_found_in_trash'  => esc_html__( '{Your Label}', '{your text domain}' ),
	'menu_name'           => esc_html__( '{Your Label}', '{your text domain}' ),
	'attributes'          => esc_html__( '{Your Label}', '{your text domain}' ),
	'item_published'      => esc_html__( '{Your Label}', '{your text domain}' ),
	'item_updated'        => esc_html__( '{Your Label}', '{your text domain}' ),
);

$args = array(
	'labels'             => $labels,
	'menu_icon'          => plugin_dir_url( __FILE__ ) . '{your image path and name}',
	'public'             => false,
	'publicly_queryable' => false,
	'exclude_from_search' => true,
	'show_ui'            => true,
	'show_in_menu'       => 'woocommerce',
	'query_var'          => true,
	'rewrite'            => true,
	'capability_type'    => 'post',
	'has_archive'        => true,
	'hierarchical'       => false,
	'menu_position'      => 30,
	'rewrite'            => array(
		'slug'       => '{your-custom-post-type}',
		'with_front' => false,
	),
	'supports'           => array( 'title', 'page-attributes' ),
);

register_post_type( '{your-custom-post-type}', $args );

Show your all menus/submenus and custom post types in one submenu

  • Show custom post types with the help of the above code to show in the submenu.
  • Add your settings pages by using of add_sub_menu() function.
add_submenu_page(
	'woocommerce', // Your menu page slug
	esc_html__( '{Your Label}', '{your text domain}' ), // title of page
	esc_html__( '{Your Label}', '{your text domain}' ), // title of menu
	'manage_woocommerce', // capability type to access this menu. normally manage_options. 
	'{your submenu slug}',
	{callback function},
	5 // Priority/position of sub menu
);

Display tabs on your custom post type and settings pages

To render our tabs, you need to use the “all_admin_notices” hook in your code. This hook is normally used to display notices on every admin page to show important messages about plugins, themes, or sites. We are using it to display the tabs on every page of our plugin. You need additional two functions to get all screen ids of your plugin and one function to get the current tab index to mark it as an active tab.

add_action('all_admin_notices', 'display_tabs', 5);

function display_tabs() {
	global $post, $typenow;
	$screen = get_current_screen();
	// print_r( $screen ); // uncomment this page code to view the id of your screen.
	// exit;
	// handle tabs on the relevant WooCommerce pages
	if ($screen && in_array($screen->id, $this->get_tab_screen_ids(), true)) {
		// List of your tabs.
		$tabs = array(
			'tab_one_index'        => array(
				'title' => __('{your title', '{your text domain}'), // title of tab
				'url'   => admin_url('edit.php?post_type={your custom post type}'), // Url of tab
			),
			'tab_two_index'    => array(
				'title' => __('{your title}', 'addify_rfq'), // title of tab
				'url'   => admin_url('admin.php?page={submenu-slug}'), // URL of tab
			),
		);

		if (is_array($tabs)) { ?>
			<div class="wrap woocommerce">
				<h2 class="nav-tab-wrapper woo-nav-tab-wrapper">
					<?php 
					$current_tab = $this->get_current_tab();
					foreach ($tabs as $id => $tab_data) {
						$class = $id === $current_tab ? array('nav-tab', 'nav-tab-active') : array('nav-tab');
						printf('<a href="%1$s" class="%2$s">%3$s</a>', esc_url($tab_data['url']), implode(' ', array_map('sanitize_html_class', $class)), esc_html($tab_data['title']));
					} 
					?>
				</h2>
			</div>
			<?php 
		}
	}
}

Get all screen IDs of your pages.

function get_tab_screen_ids() {
	$tabs_screens = array(
		'{your-custom-post-type}',
		'edit-{your-custom-post-type}',
		'woocommerce_page_{sub_menu_page_slug}', // replace woocommerce with menu slug if your are using any other menu
	);
	return $tabs_screens;
}

how to get the current screen and tab.

function get_current_tab() {
	$screen = get_current_screen();
	switch ($screen->id) {
		case '{your-custom-post-type}':
		case 'edit-{your-custom-post-type}':
			return 'tab_one_index';
		case 'woocommerce_page_{sub_menu_page_slug}': // replace woocommerce with menu slug if your are using any other menu
			return 'tab_two_index';
	}
}

How to add only one submenu for all pages

It is a hack. We are going to remove the submenu of all pages except the currently active page. Use the remove_sub_menu() function in the callback of the admin_menu hook. Beware of it, try to use the higher priority of this hook to run it at last. So your submenu pages were first added to the menu and then removed from the menu. To make it more professional, use the same title for each submenu. Now it is ready to present. End users will catch it as one submenu and all of the pages are attached to it, but actually, there are numerous submenus and pages.
// conditionally remove duplicate submenu link
add_action('admin_menu', 'remove_submenu_link', 100);
function remove_submenu_link() {
	global $pagenow, $typenow;

	if (( 'edit.php' === $pagenow && '{your-custom-post-type}' === $typenow )
		|| ( 'post.php' === $pagenow && isset($_GET['post']) && '{your-custom-post-type}' === get_post_type( sanitize_text_field( $_GET['post'] ) ) )
	) {
		remove_submenu_page('woocommerce', '{sub-menu-page-slug}');
		
	} elseif ( ( 'admin.php' === $pagenow && isset($_GET['page']) && '{sub-menu-page-slug}' ===  sanitize_text_field( $_GET['page'] ) ) ) {

		remove_submenu_page('woocommerce', 'edit.php?post_type={your-custom-post-type}');
		
	} else {

		//Default submenu to show.
		remove_submenu_page('woocommerce', '{sub-menu-page-slug}');
	}
}

Leave a Reply

Scroll to Top