PHPwordpressintermediate
Register Custom Post Type
Complete example of registering a custom post type with all common options
Faisal Yaqoob
January 9, 2025
#custom-post-type#wordpress#development#cpt
Code
php
1 function register_portfolio_post_type() { 2 $labels = array( 3 'name' => _x('Portfolio Items', 'Post type general name', 'textdomain'), 4 'singular_name' => _x('Portfolio Item', 'Post type singular name', 'textdomain'), 5 'menu_name' => _x('Portfolio', 'Admin Menu text', 'textdomain'), 6 'name_admin_bar' => _x('Portfolio Item', 'Add New on Toolbar', 'textdomain'), 7 'add_new' => __('Add New', 'textdomain'), 8 'add_new_item' => __('Add New Portfolio Item', 'textdomain'), 9 'new_item' => __('New Portfolio Item', 'textdomain'), 10 'edit_item' => __('Edit Portfolio Item', 'textdomain'), 11 'view_item' => __('View Portfolio Item', 'textdomain'), 12 'all_items' => __('All Portfolio Items', 'textdomain'), 13 'search_items' => __('Search Portfolio Items', 'textdomain'), 14 'parent_item_colon' => __('Parent Portfolio Items:', 'textdomain'), 15 'not_found' => __('No portfolio items found.', 'textdomain'), 16 'not_found_in_trash' => __('No portfolio items found in Trash.', 'textdomain'), 17 'featured_image' => _x('Portfolio Cover Image', 'Overrides the "Featured Image" phrase', 'textdomain'), 18 'set_featured_image' => _x('Set cover image', 'Overrides the "Set featured image" phrase', 'textdomain'), 19 'remove_featured_image' => _x('Remove cover image', 'Overrides the "Remove featured image" phrase', 'textdomain'), 20 'use_featured_image' => _x('Use as cover image', 'Overrides the "Use as featured image" phrase', 'textdomain'), 21 'archives' => _x('Portfolio archives', 'The post type archive label', 'textdomain'), 22 'insert_into_item' => _x('Insert into portfolio item', 'Overrides the "Insert into post" phrase', 'textdomain'), 23 'uploaded_to_this_item' => _x('Uploaded to this portfolio item', 'Overrides the "Uploaded to this post" phrase', 'textdomain'), 24 'filter_items_list' => _x('Filter portfolio items list', 'Screen reader text for the filter links', 'textdomain'), 25 'items_list_navigation' => _x('Portfolio items list navigation', 'Screen reader text for the pagination', 'textdomain'), 26 'items_list' => _x('Portfolio items list', 'Screen reader text for the items list', 'textdomain'), 27 ); 28
29 $args = array( 30 'labels' => $labels, 31 'public' => true, 32 'publicly_queryable' => true, 33 'show_ui' => true, 34 'show_in_menu' => true, 35 'query_var' => true, 36 'rewrite' => array('slug' => 'portfolio'), 37 'capability_type' => 'post', 38 'has_archive' => true, 39 'hierarchical' => false, 40 'menu_position' => 5, 41 'menu_icon' => 'dashicons-portfolio', 42 'show_in_rest' => true, // Enable Gutenberg editor 43 'supports' => array('title', 'editor', 'author', 'thumbnail', 'excerpt', 'custom-fields', 'revisions'), 44 ); 45
46 register_post_type('portfolio', $args); 47 } 48 add_action('init', 'register_portfolio_post_type');
Register Custom Post Type
A comprehensive example of registering a custom post type in WordPress with all the common options configured. This creates a "Portfolio" post type with full support for the block editor, featured images, and custom taxonomies.
function register_portfolio_post_type() {
$labels = array(
'name' => _x('Portfolio Items', 'Post type general name', 'textdomain'),
'singular_name' => _x('Portfolio Item', 'Post type singular name', 'textdomain'),
'menu_name' => _x('Portfolio', 'Admin Menu text', 'textdomain'),
'name_admin_bar' => _x('Portfolio Item', 'Add New on Toolbar', 'textdomain'),
'add_new' => __('Add New', 'textdomain'),
'add_new_item' => __('Add New Portfolio Item', 'textdomain'),
'new_item' => __('New Portfolio Item', 'textdomain'),
'edit_item' => __('Edit Portfolio Item', 'textdomain'),
'view_item' => __('View Portfolio Item', 'textdomain'),
'all_items' => __('All Portfolio Items', 'textdomain'),
'search_items' => __('Search Portfolio Items', 'textdomain'),
'parent_item_colon' => __('Parent Portfolio Items:', 'textdomain'),
'not_found' => __('No portfolio items found.', 'textdomain'),
'not_found_in_trash' => __('No portfolio items found in Trash.', 'textdomain'),
'featured_image' => _x('Portfolio Cover Image', 'Overrides the "Featured Image" phrase', 'textdomain'),
'set_featured_image' => _x('Set cover image', 'Overrides the "Set featured image" phrase', 'textdomain'),
'remove_featured_image' => _x('Remove cover image', 'Overrides the "Remove featured image" phrase', 'textdomain'),
'use_featured_image' => _x('Use as cover image', 'Overrides the "Use as featured image" phrase', 'textdomain'),
'archives' => _x('Portfolio archives', 'The post type archive label', 'textdomain'),
'insert_into_item' => _x('Insert into portfolio item', 'Overrides the "Insert into post" phrase', 'textdomain'),
'uploaded_to_this_item' => _x('Uploaded to this portfolio item', 'Overrides the "Uploaded to this post" phrase', 'textdomain'),
'filter_items_list' => _x('Filter portfolio items list', 'Screen reader text for the filter links', 'textdomain'),
'items_list_navigation' => _x('Portfolio items list navigation', 'Screen reader text for the pagination', 'textdomain'),
'items_list' => _x('Portfolio items list', 'Screen reader text for the items list', 'textdomain'),
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array('slug' => 'portfolio'),
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'menu_position' => 5,
'menu_icon' => 'dashicons-portfolio',
'show_in_rest' => true, // Enable Gutenberg editor
'supports' => array('title', 'editor', 'author', 'thumbnail', 'excerpt', 'custom-fields', 'revisions'),
);
register_post_type('portfolio', $args);
}
add_action('init', 'register_portfolio_post_type');
Key Options Explained
- show_in_rest: Enables the block (Gutenberg) editor
- has_archive: Creates an archive page at
/portfolio/ - menu_position: Controls where it appears in admin menu (5 = below Posts)
- supports: Which editor features are available (title, editor, featured image, etc.)
- rewrite: Customizes the URL slug
Next Steps
After adding this code, remember to:
- Flush rewrite rules by visiting Settings > Permalinks
- Register custom taxonomies if needed
- Create custom templates (
single-portfolio.php,archive-portfolio.php)
Related Snippets
WordPress Maintenance Mode
Put your WordPress site in maintenance mode while keeping admin access
PHPwordpressbeginner
phpPreview
// Enable maintenance mode for non-admin users
function custom_maintenance_mode() {
// Allow admin access
if (current_user_can('edit_themes') || is_user_logged_in()) {
...#wordpress#maintenance#development+1
11/8/2025
View
WordPress Custom Breadcrumbs
Create SEO-friendly breadcrumb navigation without plugins
PHPwordpressintermediate
phpPreview
// Display breadcrumbs
function custom_breadcrumbs() {
// Settings
$separator = ' » ';
...#wordpress#breadcrumbs#navigation+2
11/15/2025
View
Create Custom WordPress REST API Endpoint
Add custom REST API endpoints to extend WordPress functionality
PHPwordpressintermediate
phpPreview
// Register custom REST API endpoint
function register_custom_api_endpoint() {
register_rest_route('custom/v1', '/posts', array(
'methods' => 'GET',
...#wordpress#rest-api#api+2
11/14/2025
View