Function — Add custom post types as plugins - martindubenet/Wordpress GitHub Wiki
NOTES:1. Adding the labels
'thisTheme'
makes it compatible with the multi-lingual plugin WPML.2. You need to set your permanlinks to/%category%/%postname%/
in other to access the posts generated from those custom types.
Custom Post Types (CTPs)
It is a best practice to set Custom Post Types within a dedicated Plugin instead on the theme's functions.php
file. Since CPTs are related to database contentsRefer to this tutorial: « WordPress Functionality Plugins » from Css-Tricks to learn how.
You can find online custom Post Type generator such as cpt-generator.propernoun.co that will save you a lot of time.
Render a CPT as a template file
We have two options here depending on the design requirements:
- Either a « Template Part »,
- Or an entire « Template File ».
Template Parts
/template-parts/content-
register_post_type()
.php
Rely on parts if only the main content area differs from the default post type. If, like a « default (blog) post type » your CPTs contents are :
- Relative to a time line,
- Same navigation logic of «Previous post» and «Next post» navigation.
- Same page header (
<h1>
) has your blog post,
This partial logic is embeded in Wordpress template hierchy. A native get_template_part()
function is available.
Template Files
The singular post template used when a visitor requests a single post from a custom post type. For example, /singular-book.php
would be used for displaying single posts from a custom post type named book. The /index.php
used if a specific query template for the custom post type is not present.
Simply duplicate & rename the singular.php
to your registered post-type value :
/singular-
register_post_type()
.php
Render a list of your CPTs
WP_Query is a class used in WordPress theming that accepts a variety of parameters to request and fetch posts around those parameters. Use it lo loop within your CPTs and display it in a page.
Gutenberg editor
In the code snippet above, you need to set 'show_in_rest' => true
to enable the new Gutenberg editor in custom post-type.
Custom Fields Metabox
NOTES: After using it on a project I strongly recommand to rely on the plugin Advanced Custom Fields (ACF).
- From your theme or plugin :In the code snippet where you declare the custom post type, set within the
$args
array keysupport
the'custom_fields'
as a value. If more then one values seperate them with comas (ex:'other_value', 'custom_fields'
). - From the dashboard :Follow this tutorial: https://kaspars.net/blog/custom-fields-metabox-gutenberg
Translation for multilangue support
slug
translation via Permalinks
Translating the array( 'slug' )
of the rewrite
parameter does not support the usual gettext translation properly. It just does not translate it at all. Therefor Christopher Davis shared a workaround on his github, «cpt-permalinks.php».
1st Step:
I download his «Custom-Post-Type Base» plugin file in my theme/plugin, then I include the file within my /functions.php
file, previous to my own CPT function:
// load `function wpse30021_cpt_base`
include_once(inc/cpt-permalinks.php);
2nd Step
Within my CPT function, I copy/paste this parameter line within in the $args
array:
'rewrite' => array( 'slug' => get_option( 'wpse30021_cpt_base' ) ),`
CPT Models
plugin name | theme template | Structured data schema |
---|---|---|
posttype-jobpost |
/single-jobpost.php |
Google job posting |
posttype-portfolio |
/single-portfolio.php |
CreativeWork |
posttype-wine |
/single-wines.php |
Winery and Product |
Jobpost CPT
// Register Custom Post Type for Job Post.
function customTheme_jobPostType_init() {
$labels = array(
'name' => _x( 'Jobs', 'post type general name', 'thisTheme' ),
'singular_name' => _x( 'Job', 'post type singular name', 'thisTheme' ),
'menu_name' => __( 'Job posts', 'admin menu', 'thisTheme' ),
'add_new_item' => __( 'Add New Job Post', 'thisTheme' ),
'new_item' => __( 'New Job Post', 'thisTheme' ),
'edit_item' => __( 'Edit Job Post', 'thisTheme' ),
'view_item' => __( 'View Job Post', 'thisTheme' ),
'all_items' => __( 'All Job Posts', 'thisTheme' ),
'search_items' => __( 'Search Job Posts', 'thisTheme' ),
'parent_item_colon' => __( 'Parent Job Posts:', 'thisTheme' ),
'not_found' => __( 'No job posts found.', 'thisTheme' ),
'not_found_in_trash' => __( 'No job posts found in Trash.', 'thisTheme' )
);
$args = array(
'capability_type' => 'post',
'can_export' => true,
'description' => __( 'Description.', 'thisTheme' ),
'has_archive' => false,
'hierarchical' => false,
'labels' => $labels,
'menu_position' => 5, // positionned below `posts` in the side Admin Menu
'menu_icon' => 'dashicons-id', // developer.wordpress.org/resource/dashicons/#id
'public' => true,
'publicly_queryable' => true,
'query_var' => true,
//'rewrite' => array( 'slug' => 'job-post' ), // url rewriting for SEO
'show_in_menu' => true,
'show_in_rest' => true, // true enables gutenberg editor
'show_ui' => true,
'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'custom_fields', 'excerpt', 'comments' ),
'taxonomies' => array('post_tag', 'category')
);
register_post_type( 'jobpost', $args );
}
add_action( 'init', 'customTheme_jobPostType_init' );
💼 Portfolio CPT
/* Register Custom Post Type for Portfolio */
function cw_post_type() {
register_post_type( 'portfolio',
array(
'labels' => array(
'name' => __( 'Portfolio' ),
'singular_name' => __( 'Portfolio' )
),
'has_archive' => true,
'public' => true,
//'rewrite' => array('slug' => 'portfolio'),
'show_in_rest' => true,
'supports' => array('editor', 'thumbnail', 'custom_fields', 'excerpt')
'taxonomies' => array('post_tag', 'category')
)
);
}
add_action( 'init', 'cw_post_type' );
🍷 Wines
// Register Custom Post Type for Wine Bottles
function custom_wine_post_type() {
$labels = array(
'name' => _x('Wines', 'Post Type General Name', 'posttype wine'),
'singular_name' => _x('Wine', 'Post Type Singular Name', 'posttype wine'),
'add_new' => __('Add New', 'posttype wine'),
'add_new_item' => __('Add A New Wine', 'posttype wine'),
'all_items' => __('All Wines', 'posttype wine'),
'archives' => __('Wine Archives', 'posttype wine'),
'edit_item' => __('Edit Item', 'posttype wine'),
'featured_image' => __('Product Image', 'posttype wine'),
'filter_items_list' => __('Filter Wines List', 'posttype wine'),
'insert_into_item' => __('Post Types', 'posttype wine'),
'items_list' => __('Wines List', 'posttype wine'),
'items_list_navigation' => __('Wines List Navigation', 'posttype wine'),
'menu_name' => __('Wine Bottles', 'posttype wine'),
'name_admin_bar' => __('Add New', 'posttype wine'),
'new_item' => __('New Wine', 'posttype wine'),
'not_found' => __('No Wine Found', 'posttype wine'),
'not_found_in_trash' => __('Not Found In Trash', 'posttype wine'),
'parent_item_colon' => __('Parent Item', 'posttype wine'),
'remove_featured_image' => __('Remove Product Image', 'posttype wine'),
'search_items' => __('Search A Wine', 'posttype wine'),
'set_featured_image' => __('Set Product Image', 'posttype wine'),
'update_item' => __('Update Item', 'posttype wine'),
'uploaded_to_this_item' => __('Uploaded To This Product', 'posttype wine'),
'use_featured_image' => __('Use As Product Image', 'posttype wine'),
'view_item' => __('View Wine', 'posttype wine'),
);
$args = array(
'capability_type' => 'page',
'can_export' => true,
'description' => __('Wine product page', 'posttype wine'),
'exclude_from_search' => false,
'label' => __('Post Type', 'posttype wine'),
'labels' => $labels,
'has_archive' => true,
'hierarchical' => false,
'menu_position' => 5,
'publicly_queryable' => true,
'public' => true,
'show_in_admin_bar' => true,
'show_in_menu' => true,
'show_in_nav_menus' => true,
'show_in_rest' => true, // true enables gutenberg editor
'show_ui' => true,
'supports' => array('editor', 'title', 'trackbacks', 'content', 'revisions', 'excerpt', 'custom_fields', 'author', 'post_attributes', 'featured_image', 'post_formats', 'comments'),
'taxonomies' => array('post_tag', 'category')
);
register_post_type('wines', $args);
}
add_action('init', 'custom_wine_post_type', 0);