Creating a Custom Post Type in WordPress Plugin

Posted on 18th June 2023

In this article, we will be discussing how to create a custom post type in a WordPress plugin. WordPress plugins are a great way to add functionality to your WordPress site without having to edit the core code of WordPress. By creating a custom post type in a plugin, you can add any type of content you want to your WordPress site, such as a portfolio, testimonials, or even a custom product post type.

Creating a Custom Post Type

To create a custom post type, you first need to create a new file in your plugin directory. For this example, we will be creating a file called “my-plugin-post-type.php”.

In this file, you will need to add the following code:

_x( ‘My Plugin Post Type’, ‘Post Type General Name’, ‘text_domain’ ),
‘singular_name’ => _x( ‘My Plugin Post Type’, ‘Post Type Singular Name’, ‘text_domain’ ),
‘menu_name’ => __( ‘My Plugin Post Type’, ‘text_domain’ ),
‘name_admin_bar’ => __( ‘My Plugin Post Type’, ‘text_domain’ ),
‘archives’ => __( ‘Item Archives’, ‘text_domain’ ),
‘attributes’ => __( ‘Item Attributes’, ‘text_domain’ ),
‘parent_item_colon’ => __( ‘Parent Item:’, ‘text_domain’ ),
‘all_items’ => __( ‘All Items’, ‘text_domain’ ),
‘add_new_item’ => __( ‘Add New Item’, ‘text_domain’ ),
‘add_new’ => __( ‘Add New’, ‘text_domain’ ),
‘new_item’ => __( ‘New Item’, ‘text_domain’ ),
‘edit_item’ => __( ‘Edit Item’, ‘text_domain’ ),
‘update_item’ => __( ‘Update Item’, ‘text_domain’ ),
‘view_item’ => __( ‘View Item’, ‘text_domain’ ),
‘view_items’ => __( ‘View Items’, ‘text_domain’ ),
‘search_items’ => __( ‘Search Item’, ‘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 item’, ‘text_domain’ ),
‘uploaded_to_this_item’ => __( ‘Uploaded to this item’, ‘text_domain’ ),
‘items_list’ => __( ‘Items list’, ‘text_domain’ ),
‘items_list_navigation’ => __( ‘Items list navigation’, ‘text_domain’ ),
‘filter_items_list’ => __( ‘Filter items list’, ‘text_domain’ ),
);
$args = array(
‘label’ => __( ‘My Plugin Post Type’, ‘text_domain’ ),
‘description’ => __( ‘This is a custom post type for my plugin’, ‘text_domain’ ),
‘labels’ => $labels,
‘supports’ => array( ‘title’, ‘editor’, ‘thumbnail’ ),
‘taxonomies’ => array( ‘category’, ‘post_tag’ ),
‘hierarchical’ => false,
‘public’ => true,
‘show_ui’ => true,
‘show_in_menu’ => true,
‘menu_position’ => 5,
‘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( ‘my_plugin_post_type’, $args );

}
add_action( ‘init’, ‘my_plugin_register_post_type’, 0 );

?>

In the code above, we are first defining the labels for our custom post type. These labels will be used throughout the WordPress admin area when managing our custom post type.

We then define our $args array, which contains all the settings for our custom post type. For a full list of all the available settings, please see the WordPress Codex.

Finally, we register our custom post type using the register_post_type() function.

Adding Custom Fields to a Custom Post Type

Custom fields can be added to a custom post type to add additional data to each post. In our example, we will be adding a custom field for a “Client” name.

First, you need to add the following code to your plugin file:

This code hooks into the “add_meta_boxes” and “save_post” actions to add and save our custom fields, respectively.

Next, we need to define the my_plugin_add_custom_fields() function, which will add our custom fields to the “My Plugin Post Type” post type:

In the code above, we are using the add_meta_box() function to add our custom fields to the post editor screen for the “My Plugin Post Type” post type.

We then need to define the my_plugin_show_custom_fields() function, which will output the HTML for our custom fields:

post_type );

// Get the post type slug
$post_type_slug = $post_type->rewrite[‘slug’];

// Get the post ID
$post_id = $post->ID;

// Get the custom fields
$client_name = get_post_meta( $post_id, ‘_my_plugin_client_name’, true );

// Nonce field for security
wp_nonce_field( ‘my_plugin_meta_box_nonce’, ‘my_plugin_meta_box_nonce’ );

// Form field for the client name
echo ‘

‘;
echo ‘

‘;
}

?>

In the code above, we are first getting the post type object and the post type slug. We then get the post ID and the custom field value.

We then create a nonce field for security and finally output a form field for the client name.

Next, we need to define the my_plugin_save_custom_fields() function, which will save our custom field values when the post is

In your plugin file, you will need to register your custom post type using the register_post_type() function. This function takes an array of arguments which you will need to specify. The following is an example of a custom post type being registered:

_x( ‘Custom Post Type Name’, ‘Post Type General Name’, ‘text_domain’ ),
‘singular_name’ => _x( ‘Custom Post Type’, ‘Post Type Singular Name’, ‘text_domain’ ),
‘menu_name’ => __( ‘Custom Post Type’, ‘text_domain’ ),
‘name_admin_bar’ => __( ‘Custom Post Type’, ‘text_domain’ ),
‘archives’ => __( ‘Custom Post Type Archives’, ‘text_domain’ ),
‘attributes’ => __( ‘Custom Post Type Attributes’, ‘text_domain’ ),
‘parent_item_colon’ => __( ‘Parent Custom Post Type:’, ‘text_domain’ ),
‘all_items’ => __( ‘All Custom Post Types’, ‘text_domain’ ),
‘add_new_item’ => __( ‘Add New Custom Post Type’, ‘text_domain’ ),
‘add_new’ => __( ‘Add New’, ‘text_domain’ ),
‘new_item’ => __( ‘New Custom Post Type’, ‘text_domain’ ),
‘edit_item’ => __( ‘Edit Custom Post Type’, ‘text_domain’ ),
‘update_item’ => __( ‘Update Custom Post Type’, ‘text_domain’ ),
‘view_item’ => __( ‘View Custom Post Type’, ‘text_domain’ ),
‘view_items’ => __( ‘View Custom Post Types’, ‘text_domain’ ),
‘search_items’ => __( ‘Search Custom Post Type’, ‘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 Custom Post Type’, ‘text_domain’ ),
‘uploaded_to_this_item’ => __( ‘Uploaded to this Custom Post Type’, ‘text_domain’ ),
‘items_list’ => __( ‘Custom Post Type list’, ‘text_domain’ ),
‘items_list_navigation’ => __( ‘Custom Post Type list navigation’, ‘text_domain’ ),
‘filter_items_list’ => __( ‘Filter Custom Post Type list’, ‘text_domain’ ),
);
$args = array(
‘label’ => __( ‘Custom Post Type’, ‘text_domain’ ),
‘description’ => __( ‘Custom Post Type Description’, ‘text_domain’ ),
‘labels’ => $labels,
‘supports’ => array( ‘title’, ‘editor’, ‘thumbnail’, ),
‘taxonomies’ => array( ‘category’, ‘post_tag’ ),
‘hierarchical’ => false,
‘public’ => true,
‘show_ui’ => true,
‘show_in_menu’ => true,
‘menu_position’ => 5,
‘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( ‘custom_post_type’, $args );

}
add_action( ‘init’, ‘custom_post_type’, 0 );

?>