The Post Types Unlimited plugin, also known as “PTU”, allows you to easily add custom post types and taxonomies to your WordPress site. I created this plugin because other plugins, such as the popular Custom Post Type UI plugin, are bloated & full of upsells. It is a great add-on for any site that requires custom types and/or taxonomies.

In this guide, I will show you how to add custom options to the post type and taxonomy registration screens. This way, you can provide built-in integration for your theme so anyone using it can have more control over their custom post types and taxonomies.

This guide is primarily focused around classic themes, since block themes have access to the site editor where the end user can fully customize their post types and taxonomies.

Why Add Custom Options to the Post Types Unlimited Plugin

As a theme developer you may be wondering why should you add custom options to the PTU plugin. We’ll, by adding options to the plugin you can make it easier for the end user to control the design of their custom post types and taxonomies. My Total Theme is a great example.

Here is a screenshot showing the “Single Post” settings added by the Total theme:

Total WordPress theme post types unlimited single post settings

This provides the user with the following useful fields:

  • Use Blank Template: Enable to usee a blank template for the single post type posts (aka no header/footer)
  • Dynamic Template: Select a template for the single post display.
  • Title: Modifies the default single post page header title text.
  • Title Style: Select the title style (can be used to hide the page header title).
  • Title Tag: Select the page header title HTML tag (h1,h2,h3,h4,h5,h6,div).
  • Layout: Select the layout for the single post type posts (no sidebar, left sidebar, right sidebar, full screen, etc).
  • Next/Previous: Enables the next and previous links at the bottom of the post before the footer (usually disabled when using a dynamic template as you can add the next/prev directly in the dynamic template).

There are actually a lot more settings if a dynamic template isn’t set, but most of the time users will be creating dynamic templates for their post types.

As you can see, when creating custom post types with Total, you will have a lot of control over how the single posts look. Generally, themes are coded so that custom post type archives and single posts always look the same. Total also includes settings for custom taxonomies.

This way, users don’t have to use hooks, filters or template parts to modify their custom post types and taxonomies. This makes it possible for non-developers to create more advanced websites.

How Post Types Unlimited Works

The Post Types Unlimited plugin works using core WordPress functionality. Custom post types and taxonomies are actually registered as post types themselves. And the settings when registering/editing a post type or taxonomy are done via a custom metabox.

Registered custom post types are saved in a custom post type named ptu and custom taxonomies are saved in a custom post type named ptu_tax.

When the page loads the plugin hooks into the init hook to query the ptu and ptu_tax post types, loop through and register them. The custom post types and taxonomies are stored in a class variable so they can be retrieved quickly later.

Retrieving a List of Post Types & Taxonomies

These are the two functions you can use to retrieve the custom post types and taxonomies:

  • PTUPostTypes::get_registered_items() – returns an array of post types, where the key is the post type name and the value is the ID of the ptu post type post.
  • PTUTaxonomies::get_registered_items() – returns an array of registered taxonomies, where the key is the taxonomy name and the value is the ID of the ptu_tax post type post.

If you need to check or loop through user created custom post types or taxonomies you can use those to public methods.

Retrieving a Post Type or Taxonomy Setting Value

I mentioned previously that the post type and taxonomy settings are done via a metabox, which means they are stored as custom fields. To get the value of any setting you would use the core get_post_meta() function like such:

// Get post type setting value.
get_post_meta( 'post_type_name', '_ptu_{option_id}', true );

// Get taxonomy setting value.
get_post_meta( 'taxonomy_name', '_ptu_{option_id}', true );

The Post Types Unlimited plugin automatically adds a _ptu_ prefix to the custom fields when they are saved. Make sure to include this prefix when getting the value of your own options. I will explain in greater detail with some examples later on.

How to Add Custom Options to the Post Type & Taxonomy Add New/Edit Screens

Adding options is super simple and it’s done by creating new tabs to the default metabox. You can add new tabs to both the post type and the taxonomy new/edit screens. This is done, by hooking into the ptu/posttypes/meta_box_tabs and ptu/taxonomies/meta_box_tab filters.

Here is an example of adding a new tab named “Cool Theme Settings” with a few custom options. This code will add the same settings to both the post type and taxonomy setting pages.

/**
 * Add custom options to the Post Types Unlimited Plugin.
 *
 * @link https://www.wpexplorer.com/post-types-unlimited-custom-options/
 */
function wpexplorer_add_ptu_type_tabs( array $tabs ): array {
	$tabs[] = [
		'id'     => 'themename_settings',
		'title'  => esc_html__( 'Cool Theme Settings', 'themename' ),
		'fields' => [
			[
				'name' => esc_html__( 'Check Option', 'themename' ),
				'id'   => 'check_option',
				'type' => 'checkbox',
			],
			[
				'name' => esc_html__( 'Text Option', 'themename' ),
				'id'   => 'text_option',
				'type' => 'text',
			],
			[
				'name'    => esc_html__( 'Custom Select Option', 'themename' ),
				'id'      => 'select_option',
				'type'    => 'select',
				'choices' => [
					''         => esc_html__( '- Select -', 'themename' ),
					'option_1' => esc_html__( 'Option 1', 'themename' ),
					'option_2' => esc_html__( 'Option 2', 'themename' ),
					'option_3' => esc_html__( 'Option 3', 'themename' ),
				],
			],
			[
				'name' => esc_html__( 'Image Select Option', 'themename' ),
				'id'   => 'image_size_option',
				'type' => 'image_size',
			],
		],
	];
	return $tabs;
}
add_filter( 'ptu/posttypes/meta_box_tabs', 'wpexplorer_add_ptu_type_tabs' );
add_filter( 'ptu/taxonomies/meta_box_tabs', 'wpexplorer_add_ptu_type_tabs' );

This code would add a new tab that looks as follows:

Option Field Types

The sample snippet should be pretty straight forward but it only shows how to add a few field types. Below is a table of all field types with a description and the list of extra arguments that can be added for the type.

Field Type Description Extra Args
text Basic text field. (bool) required
(int) maxlength
number Number type field. (int) step
(int) min
(int) max
textarea Textarea. (int) rows
checkbox Checkbox.
select Custom select dropdown. (array) choices
multi_select Multiple checkboxes grouped together. (array) choices
page Select option that returns all pages.
image_size Select option that returns all defined image sizes.
taxonomy Select option that returns all registered public taxonomy names.
dashicon Dashicon icon select.

Conditional (show/hide) Fields

The metabox class has the ability to show/hide tabs and fields via a condition key. You can add a new condition key to the tab array to control the tab display or to individual options to control the visibility of the option.

The conditional argument works via an array using the following format:

'condition' => [ 'setting_to_check', 'operator', 'value_to_check' ]
  • setting_to_check: (string) setting ID to check the value of.
  • operator: (string) can be “=” or “!=”.
  • value_to_check: (string) the expected value you want to be equal or not equal to.

For example, let’s say you wanted to add a tab that only displays if the post type “public” setting is enabled you can do so like such:

function wpexplorer_add_ptu_type_tabs( array $tabs ): array {
	$tabs[] = [
		'id'        => 'themename_public_settings',
		'title'     => esc_html__( 'Public Settings', 'themename' ),
		'condition' => [ 'public', '=', 'true' ], // !!! CONDITIONAL CHECK !!!
		'fields'    => [ ]
	];
	return $tabs;
}
add_filter( 'ptu/posttypes/meta_box_tabs', 'wpexplorer_add_ptu_type_tabs' );

Or lets say you are adding 2 options but the second option should only display if the first option is enabled. You can do so like such:

function wpexplorer_add_ptu_type_tabs( array $tabs ): array {
	$tabs[] = [
		'id'        => 'themename_public_settings',
		'title'     => esc_html__( 'Public Settings', 'themename' ),
		'fields'    => [
			[
				'name' => esc_html__( 'Check Option', 'themename' ),
				'id'   => 'check_option',
				'type' => 'checkbox',
			],
			[
				'name'      => esc_html__( 'Conditional Text Option', 'themename' ),
				'id'        => 'text_option',
				'type'      => 'text',
				'condition' => [ 'check_option', '=', 'true' ], // !!! CONDITIONAL CHECK !!!
			],
		]
	];
	return $tabs;
}
add_filter( 'ptu/posttypes/meta_box_tabs', 'wpexplorer_add_ptu_type_tabs' );

By using conditional checks you can provide a better user experience if certain options are not needed depending on the value of other options. Just note that the conditional functionality is very minimal and will only allow you to check a single option at a time against a single value.

Retrieving Your Custom Option Values

Now that you know how to add custom options I will explain how to get the value of those options. Earlier I explained that you will use the core get_post_meta() function to grab the value of your fields. But in order to grab the custom field value you need to pass the correct ID based on the post type or taxonomy. I will show you how to do that.

Getting the Value of a Post Type Option

Let’s say you have an option to choose the layout for the custom post type’s single posts and the option ID is “post_layout”. So, in whatever code you are using to get the current post layout, you will want to add an extra check for your custom PTU option.

Here is an example of how to get a post type option value:

if ( is_callable( 'PTUPostTypes::get_registered_items' ) ) {
	// Get the post type.
	$post_type = get_post_type();

	// Get registered PTU post types.
	$ptu_types = PTUPostTypes::get_registered_items();

	// Check if the current post type is part of the PTU types.
	if ( isset( $ptu_types[ $post_type ] ) ) {
		$ptu_post_layout = get_post_meta( $ptu_types[ $post_type ], '_ptu_themename_post_layout', true );
	}
}

The code works by checking to see if the current post is a PTU custom post type and if so, it uses get_post_meta to grab the custom field value. Be sure to change themename_post_layout to the ID of the option you are retrieving.

Getting the Value of a Taxonomy Option

Getting the value for a taxonomy option is very similar to that of a custom post type. The difference is you need to run a check against the registered taxonomies.

Here is an example of how to get a taxonomy option value:

if ( is_callable( 'PTUTaxonomies::get_registered_items' ) ) {
	// Get the current taxonomy.
	$taxonomy = get_query_var( 'taxonomy' );

	// Get registered PTU taxonomies.
	$ptu_taxonomies = PTUTaxonomies::get_registered_items();

	// Check if the taxonomy is part of the PTU taxonomies.
	if ( isset( $ptu_taxonomies[ $taxonomy ] ) ) {
		$ptu_archive_layout = get_post_meta( $ptu_taxonomies[ $taxonomy ], '_ptu_themename_archive_layout', true );
	}
}

The code works by checking to see if the current taxonomy is a PTU custom taxonomy and if so, it uses get_post_meta to grab the custom field value. Be sure to change themename_archive_layout to the ID of the option you are retrieving.

Creating a Helper Function to Retrieve Options

To follow DRY principles I would recommend adding a helper function to your theme that you can use to get the value of a PTU post type or taxonomy. Post Types Unlimited doesn’t include a helper function because it’s not needed.

Get Post Type Option Value Helper Function

Here is a helper function for returning a post type option value:

/**
 * Get the value of a PTU post type setting.
 */
function themename_get_ptu_meta( string $post_type, string $setting_id, $default = '' ) {
	if ( is_callable( 'PTUPostTypes::get_registered_items' ) ) {
		$ptu_types = PTUPostTypes::get_registered_items();
		if ( isset( $ptu_types[ $post_type ] ) ) {
			if ( $default && ! metadata_exists( 'post', $ptu_types[ $post_type ], $setting_id ) ) {
				return $default;
			}
			return get_post_meta( $ptu_types[ $post_type ], $setting_id, true );
		}
	}
}

And here is how you would use the function:

$post_layout = themename_get_ptu_meta( get_post_type(), 'post_layout' );

Get Taxonomy Option Value Helper Function

Here is a helper function for returning a taxonomy option value:

/**
 * Get the value of a PTU taxonomy setting.
 */
function themename_get_ptu_tax_meta( string $taxonomy, string $setting_id, $default = '' ) {
	if ( is_callable( 'PTUTaxonomies::get_registered_items' ) ) {
		$ptu_taxonomies = PTUTaxonomies::get_registered_items();
		if ( isset( $ptu_taxonomies[ $taxonomy ] ) ) {
			if ( $default && ! metadata_exists( 'post', $ptu_taxonomies[ $taxonomy ], $setting_id ) ) {
				return $default;
			}
			return get_post_meta( $ptu_taxonomies[ $taxonomy ], $setting_id, true );
		}
	}
}

And here is how you would use the function:

$archive_layout = themename_get_ptu_tax_meta( get_query_var( 'taxonomy' ), 'archive_layout' );

In both helper functions you can see I’ve also added a $default parameter you can use. This will allow you to pass a default value in case custom field doesn’t exist.

Conclusion

Adding options to your theme for the Post Types Unlimited Plugin is super easy and you should do it! Especially if you are selling a premium theme, it would be very nice for your users to be able to add custom post types and taxonomies to their site and have more control over how they look without any coding knowledge.

You could also just stop selling or maintaining your own custom themes and instead become an affiliate of ThemeForest and recommend/use my Total theme.

Let me know in the comments if you have any issues or questions!

Similar Posts