Creating custom post type

Custom post type

Custom post types (CPT) are an essential part of WordPress. If you have a specific plugin installed, chances are you have custom post types set up as well. Let's go and see how can we create them on our own.

Custom post types are a useful tool if you want to create a new plugin, and you want to differentiate your posts from the rest of the native posts in the WordPress. The default post types in WordPress are: ‘post’, ‘page’, ‘attachment’, ‘revision’ and ‘nav_menu_item’. Yes, menu items are post types – sounds crazy, but it actually works pretty well.

If you’ve ever used a plugin like bbpress, WooCommerce, The Events Calendar etc. you used custom post types. Every plugin maker knows what they are and that you can do a bunch of cool stuff with them. So for today’s tutorial I’ve thought that it would be cool to show you guys how to create a custom post type, put in a meta box, and some additional fields to it and register a taxonomy for that custom post type.

Knowledge is power

The post type we’ll be creating is called: Knowledge base. I’ve been working on a site that required one, so with all the info still fresh, it’s best to use that knowledge to help you guys out :D

As always my base is plain old Twenty sixteen theme in the functions.phpfile, but I usually recommend adding this to a separate file you’ll include inside your functions file, to avoid the clutter. Or, better yet, you’ll add it in a plugin. First thing we’ll want to do is to register our CPT and our taxonomy (while we’re at it). The function that controls this is called register_post_type(). You can read more about it here.

Notice the commenting. It’s important to comment your code. No matter how unimportant you think that could be, trust me, it’s better to comment it than not. So you can see that we’ve set up the knowledgebase CPT, and we’ve set up our labels for it, and all the interesting information about it like what menu icon it should have, what its capabilities are, if it has archive page etc. One of the important thing to notice is here, is the supports argument. This will enable things like TinyMCE editor, title functionality, featured image (thumbnail), excerpts etc. The rewrite part is important, as it will handle how your slug in the url will look like. Generally you can make this a translatable string, so if you have a multi language site, you can translate it, like

You can also make it appear in your REST API by specifying show_in_rest argument in the array. Also I’ve added  register_meta_box_cb argument, which will provide a callback function that will be called when setting up the meta boxes for the edit form.
Last part in our function is the taxonomy. This is basically the custom category that goes with our custom post type.

Next, we’ll define our metabox funtion. In it you can have all sorts of things – input fields, select drop downs, textareas, checkboxes. You name it. If you have downloaded and tried our my plugin, you’ll notice that the talks section is a metabox, that has tabs in it, and you can even upload images in it. So the world is your oyster.

First we add our meta box (or more of them), then set up the function that will render it, and save it.

Knowledge base single post

Knowledge base single post with meta box added

Another thing that we can modify is the taxonomy screen. Say we want to custom order our taxonomy terms. We’d put an input field that will take in positive integers. I’ve added sidebar selectors here, colors, and even term images (like feature images) here. So this is also something that you can customize. Here we’ll take advantage of the termmeta table, that was introduced in the 4.4 version.

This will give us an input field where we can add number for our category, both in the edit category term screen and in the create screen. If we want to display that information (and make it sortable) in the table where the name of the categories are, we’ll need to add another piece of code.

First function will add the new column, the second will populate it with our term meta, third will make that column sortable, but we need to modify our sorting query. This is where last part comes in handy. The idea is the same with the sortable columns for posts, but for terms we need to use terms_clauses hook, to execute our query. The query itself is an interesting thing (at least to me). Full query, as you’re seeing in the code, looks like this:

But here we’re using $pieces array that, before we modify it looks like this:

And after modification looks like this

You can see that you’ll need to put your query in a certain keys for it to work. It’s just WordPress way of handling the custom sorting. If you were to custom sort columns in custom post screen, you’d use pre_get_posts hook. The same principle applies there. You’ll end up with something like this:

Knowledge base category screen

Knowledge base category screen

If you are wondering why I had to use custom sort, it’s because no matter what I tried, I couldn’t get them to sort. So I needed some small MySQL magic for it to work. Notice that the order parameter is absolute value of the term meta field. This limits the values to positive integers if you want the sort to work. Because the absolute value will turn negative values to positive, and the sorting wouldn’t work. There is probably a better way to handle this, but it’s good for demonstrations sake. Using term meta is a great thing since you already have this table in your database (you might as well use it, no?), plus when you remove your term, the term meta value will get removed immediately as well, which is great way to insure your database isn’t filled with junk values that serve no purpose :)

But wait! There’s more…

This is a task I admit, but I want to show you what you can do with CPT. So one more thing that you can add to it is custom column in the CPT screen. Say that you want to show categories that are associated with each post. Then just define these:

Notice that we’ve added the custom column by specifying the default fields, and then inserted the column where we want it. The advantage of this is that we can control where we put the column. The

approach will always put your column at the end. And that could look odd. Imploding the terms is better then just echoing them out, because you can delimit them with any delimiter you want (in my case it’s a comma), and you won’t have a delimiter after the last array value. Since this column is showing letters, the default alphabetic sorting will work here.

Knowledge base posts screen

Knowledge base posts screen

You can put what ever column you want – custom post meta values, last modified date. Anything you might think is important to show. The general rule is not to put unnecessary stuff in the columns. If it provides no useful information, leave it out ;)

And this is it! You’ve created your own custom post type. Congratulations. You see that you can do a lot with it. The greatest thing is that you can separate the posts further, and use it in custom queries later on. Better than bunching it all together in regular posts :D I hope this helped you and if you have any kind of question feel free to post it in the comments below. Happy coding!

Also published on Medium.

Join the Discussion