How To Create Custom Post Type In WordPress (Without Plugin)

The term of "Post Type" used to determine different types of content that can hold and display in WordPress.
By default WordPress already has several basic post types, they are:

  • post
  • page
  • attachment
  • revision
  • nav_menu_item
  • custom_css
  • customize_changeset

But sometimes there is a need to create your own version of the post.
This can be a portfolio, people, goods, etc etc

For example, let's create a post-type "Materials".

Also, we’ll create different custom taxonomies and other Tweaks in the second part of this article (category, tags, filtering)

For convenience, we will create our own function, in which we will create post type and tags with categories for it. Then we raise this function on the init hook.

First Step

Function register_post_type() - https://codex.wordpress.org/Function_Reference/register_post_type


function material_init {
$labels = array(
‘name' => esc_html__('Materials', 'themedomain' ),
'singular_name' => esc_html__('Material Item',
'themedomain' ),
'add_new' => esc_html__('Add New Item', 'themedomain'
),
'add_new_item' => esc_html__('Add New Material Item',
'themedomain' ),
'edit_item' => esc_html__('Edit Material Item',
'themedomain' ),
'new_item' => esc_html__('Add New Material Item',
'themedomain' ),
'view_item' => esc_html__('View Item', 'themedomain' ),
'search_items' => esc_html__('Search Material',
'themedomain' ),
'not_found' => esc_html__('No material items found',
'themedomain' ),
'not_found_in_trash' => esc_html__('No material items
found in trash', 'themedomain' )
);
$args = array(
'labels' => $labels,
'public' => true,
'show_ui' => true,
'menu_icon' => 'dashicons-paperclip',
'supports' => array( 'title', 'editor', 'excerpt', 'thumbnail', 'comments', 'author', 'custom-fields', 'revisions'
),
'capability_type' => 'post',
'hierarchical' => false,
'rewrite' => array( 'slug' => sanitize_title(
'material' ), 'with_front' => false ),
'menu_position' => 5,
'has_archive' => true
);
register_post_type( 'material', $args );
}
add_action( 'init', 'material_init' );

That's what we got

new post

Now let's see what these terms mean.

$post_type (string) Post Type Name

(max. 20 characters, cannot contain capital letters or spaces, symbols, numbers, also _ or -: a-z0-9_-.)

$args (array) An array of arguments.

Consider the parameters of the array $ args

$labels (array)

An array that contains labels names for the current post type./ An array of labels for this post type.

Array Arguments  

name

a general name for the post type, usually plural.

singular_name

name for one object of this post type.

 add_new

the add new text, like „Add New“ for posts in the admin panel.

        add_new_item

the header text of the newly created entry in the admin panel, like „Add New Post“ for posts in the admin panel.

edit_item

the text for editing item

new_item

the new item text

view_item

the view item text

search_items

the text for a search for this item

not_found

the text in case nothing was found

not_found_in_trash

the text if the item wasn’t’ found in a trash

all_items

the all items text

public (boolean)

Determines whether the post type is public or not. On the basis of this parameter, many others are constructed, i.e. this is a kind of pre-installation for the following parameters:

  • false
    • show_ui = false – doesn’t show user interface (UI) for this post type. publicly_queryable = false - The queries affected to this post type will not function in a template
    • exclude_from_search = true - This post type will not be taken into account when searching the site
  • show_in_nav_menus = false - This post type will be hidden from the navigation menu selection
    true

    • show_ui = true
    • publicly_queryable = true
    • exclude_from_search = false
    • show_in_nav_menus = true

menu_icon (string)

Link for an image that will be used for this post type.

You can use an icon font  Dashicons - https://developer.wordpress.org/resource/dashicons/, that is essential for WordPress core. It contains more than 150 vector images. To set an icon as featured just type its name to a parameter.

For example, post icon name is dashicons-admin-post, and URL: dashicons-admin-links. Or if you need some special icon than make it fit 16*16 pixel)
For example get_stylesheet_directory_uri() .'/img/material_icon.png'

supports (array)

Which meta boxes should be added to editing the page for this post type.

  • title — field for entering the header of the post
  • editor — text editor form
  • excerpt — meta_box for a snippet of the post
  • author — meta_box for the Author name
  • thumbnail — meta_box for the featured image, current theme must also support post-thumbnails
  • comments — if such meta_box is present then comments for this post type are allowed
  • custom-fields — this meta_box will be supported by default.
  • revisions— such meta_box will store revisions

capability_type (string or array)

This sting to use to determine capabilities to build the read, edit, and delete. Built-in types that can be used are post and page.

hierarchical
(boolean)

Whether the post type is hierarchical.

rewrite (boolean or array) Triggers the handling of rewrites for this post type. To prevent rewrites, set to false. Default: true and use $post_type as slug.

  • slug (string)
    Customize the permalink structure slug. Defaults to the $post_type value. Should be translatable.
  • with_front (bool)
    Should the permalink structure be prepended with the front base.
    Slug takes from $wp_rewite->front. Example, if your permalink structure is blog/%postname%, then your links will be: false- /material/ postname, true - /blog/material/ postname. Defaults to true.

menu_position (integer)

The position in the menu orders the post type should appear. show_in_menu must be true.

has_archive (boolean or string)

Enables post type archives. Will use $post_type as archive slug by default. Example, if post URL is - site.com/type/post_name, then archive URL will be -site.com/type.

An archive file name in the theme will be archive-type.php. Will generate the proper rewrite rules if rewrite is enabled.

After creating this new post type go to “Settings” -> “Permalinks” and just press the “Save Changes” button. This is necessary for the clean URL rules to be restored and the rules for a new post type added there.

permalinks

In the next article we will also describe how to create custom taxonomies to custom post type.