
How To Modify WordPress Custom Post Types With Child Theme
Whilst developing websites using child themes, I noticed that some parent themes I were using had too many features that bloated the user interface and confused my clients. Many of these additional 'features' were WordPress Custom Post Types (CPT). It is well-known that using child themes is a better practise than modifying the theme itself - especially if there is a chance of the parent theme being subjected to updates.
Therefore, I needed to find a way to change existing WordPress Custom Post Types using a child theme. After much trialling, testing and hacking premium themes - I found a way! And I am sharing it below…

How to change WordPress Custom Post Types with a Child Theme
I've tried this with an array of themes available from the WordPress repository and from premium theme vendors. Unfortunately, premium themes can be incredibly complex - making simple overrides in the functions.php file a nightmare. Fortunately. the method I am going to show you below is super-simple and works across every theme I have tried it with.
You'll need to make sure of the following:
- The parent theme creates WordPress Custom Post Types in the correct way - ie by registering a post type in the
functions.phpfile - Know the priority at which the register function is called for the custom post type (not essential)
- Know the name used to register the WordPress Custom Post Type by the parent theme
By accessing a global variable called $wp_post_types we can use the registered labels and arguments for any custom post type activated by our WordPress theme or Child Theme. Copy and paste the code below in to your functions.php file, and I'll explain what it does below.
add_action( 'wp_loaded', 'modify_cpt_custom_post_type', 1002 );
function modify_cpt_custom_post_type() { global $wp_post_types; $p = 'cpt';
// Someone has changed this post type, always check for that!
if ( empty ( $wp_post_types\[ $p \] )
or ! is_object( $wp_post_types\[ $p \] )
or empty ( $wp_post_types\[ $p \]->labels )
)
return;
// see get_post_type_labels()
$wp_post_types\[ $p \]->labels->name = _x( 'Post Types', 'Post Type General Name', 'text_domain' );
$wp_post_types\[ $p \]->labels->singular_name = _x( 'Post Type', 'Post Type Singular Name', 'text_domain' );
$wp_post_types\[ $p \]->labels->menu_name = __( 'Post Type', 'text_domain' );
$wp_post_types\[ $p \]->labels->name_admin_bar = __( 'Post Type', 'text_domain' );
$wp_post_types\[ $p \]->labels->archives = __( 'Item Archives', 'text_domain' );
$wp_post_types\[ $p \]->labels->parent_item_colon = __( 'Parent Item:', 'text_domain' )
$wp_post_types\[ $p \]->labels->all_items = __( 'All Items', 'text_domain' )
$wp_post_types\[ $p \]->labels->add_new_item = __( 'Add New Item', 'text_domain' )
$wp_post_types\[ $p \]->labels->add_new = __( 'Add New', 'text_domain' );
$wp_post_types\[ $p \]->labels->new_item = __( 'New Item', 'text_domain' );
$wp_post_types\[ $p \]->labels->edit_item = __( 'Edit Item', 'text_domain' );
$wp_post_types\[ $p \]->labels->update_item = __( 'Update Item', 'text_domain' );
$wp_post_types\[ $p \]->labels->view_item = __( 'View Item', 'text_domain' );
$wp_post_types\[ $p \]->labels->search_items = __( 'Search Item', 'text_domain' );
$wp_post_types\[ $p \]->labels->not_found = __( 'Not found', 'text_domain' );
$wp_post_types\[ $p \]->labels->not_found_in_trash = __( 'Not found in Trash', 'text_domain' );
$wp_post_types\[ $p \]->labels->featured_image = __( 'Featured Image', 'text_domain' );
$wp_post_types\[ $p \]->labels->set_featured_image = __( 'Set featured image', 'text_domain' );
$wp_post_types\[ $p \]->labels->remove_featured_image = __( 'Remove featured image', 'text_domain' );
$wp_post_types\[ $p \]->labels->use_featured_image = __( 'Use as featured image', 'text_domain' );
$wp_post_types\[ $p \]->labels->insert_into_item = __( 'Insert into item', 'text_domain' );
$wp_post_types\[ $p \]->labels->uploaded_to_this_item = __( 'Uploaded to this item', 'text_domain' );
$wp_post_types\[ $p \]->labels->items_list = __( 'Items list', 'text_domain' );
$wp_post_types\[ $p \]->labels->items_list_navigation = __( 'Items list navigation', 'text_domain' );
$wp_post_types\[ $p \]->labels->filter_items_list = __( 'Filter items list', 'text_domain' );
$wp_post_types\[ $p \]->label = __( 'Post Type', 'text_domain' );
$wp_post_types\[ $p \]->description = __( 'Post Type Description', 'text_domain' );
$wp_post_types\[ $p \]->supports = array( );
$wp_post_types\[ $p \]->taxonomies = array( 'category', 'post_tag' );
$wp_post_types\[ $p \]->hierarchical = false;
$wp_post_types\[ $p \]->public = true;
$wp_post_types\[ $p \]->show_ui = true;
$wp_post_types\[ $p \]->show_in_menu = true;
$wp_post_types\[ $p \]->menu_position = 5;
$wp_post_types\[ $p \]->show_in_admin_bar = true;
$wp_post_types\[ $p \]->show_in_nav_menus = true;
$wp_post_types\[ $p \]->can_export = true;
$wp_post_types\[ $p \]->has_archive = true;
$wp_post_types\[ $p \]->exclude_from_search = false;
$wp_post_types\[ $p \]->publicly_queryable = true;
$wp_post_types\[ $p \]->capability_type = 'page';
At first, we create an action hook which calls the modify_cpt_custom_post_type() function once WordPress has finished loading. In my example, I have given it the order priority of 1002 which ensures it is one of the last actions executed. This is because, sometimes, some theme authors register WordPress Custom Post Types with a priority of 999 - and so the standard of using 20 will not work. Tip: If the code above doesn't work for you, try increasing the order priority to a higher number eg, 2000.
Next, we declare the function which does the modifying. I have called it modify_cpt_custom_post_type but you are welcome to change this name for something more suitable for yourself. Remember to also change the name in the action hook too.
Inside this function, we make accessible the global $wp_post_types variable which has an array of all post types activated by our theme including WordPress Custom Post Types. The line immediately after it is the name of the WordPress Custom Post Type we are looking to change. You should change 'cpt' to the name of the Custom Post Type you are trying to target.
The remaining lines are all optional. Taken from Generate WP's Custom Post Type generator, it displays all the possible fields you can edit. Erase the ones you do not need to change, and refer to the WordPress Custom Post Types documentation to manipulate the arguments to your specification.
Be aware that this function will overwrite the values set by the parent theme. If there is only one attribute you want to change, include it in the code above - but remember all other attributes will be inherited so there is no need to repeat them.

Thanks for reading!
My name is Zahid Mahmood, and I'm one of the founders of Anterior. I started this technology blog when I was in high school and grew it to over 100,000 readers before becoming occupied with other projects. I've recently started writing again and will be posting more frequently.