
Creating custom post types is easy. Finding them afterwards…maybe not so much.
Background
Over the course of the project I’m working on, I found myself creating five different custom post types and four custom taxonomies. They accreted as I discovered more about the content. (Let this be a lesson to all you developers: start with a thorough content audit so you know what post types, taxonomies, and custom templates you need from the beginning.)
The first post type I created was “Case Studies,” because it was immediately clear that these needed to be something separate from pages. Each Case Study has a “Project Area” taxonomy.
So far, so good. I created my post type/taxonomy registration plugin, uploaded it, activated it, and presto! Case Studies showed up below Posts in my WordPress admin menu. Add some content, create a single_yld_case_studies.php
and an archive_yld_case_studies.php
template, and we’re good to go. There was the inevitable fiddling with the CSS and there were a few tricks in the code to get the archive to display in columns sorted by Project Area, but it was all pretty straightforward.
As the project progressed, I came to the conclusion that Careers needed to be a post type instead of a set of custom fields, because of the way I needed to retrieve and display them on different parts of the site. (That’s another post, about custom fields vs. custom post types.) I’d already created the Agents of Change post type, each of which was supposed to display three associated Careers on its single_yld_agent.php
page.
Three post types in, we were good. All three showed up in the admin menu, in the order in which they were registered.
I added a fourth post type: Writer’s Corner Exercises. Still okay. One of the project team members entered them and classified them with the appropriate “Episode” taxonomy.
But a week or so later I was looking back over the mockups and realized that I needed a fifth post type: Word of the Day. I added it to my post types plugin. It worked fine.
The Problem
What I didn’t notice, because I was no longer doing anything with the Case Studies (they’d been built and at least partly populated, so they were now someone else’s responsibility), was that they had been bumped off the menu.
I discovered this when the someone else who was tasked with adding taxonomy images posted a message to Basecamp saying he couldn’t find the Case Studies. I explained where to find them, but he insisted he didn’t see them.
So I logged in and was astonished to discover that there were, in fact, no Case Studies in my admin menu. They weren’t being masked by CSS or JavaScript–they just weren’t there. Yet the post type had not disappeared; I could get to the admin screens for it from the direct URL, and everything was displaying fine at the front end. The Admin Columns plugin was even showing controls for them.
WTF?
A bit of Google Fu revealed that this is a known problem in WordPress when you register post types with the menu_position
argument, if you start at any number above 25. That’s because there’s already something inhabiting 5, 10, 15, 20, and 25. There’s a big space between comments and the first separator; see the Codex for details.
So I could change my menu position from 5 to 25 and have all my post types show up in the admin menu. (Actually, they would all show up if I set menu_position to 15 or to 20, but in the first case they had Pages stuck in the middle, and in the second case, they had Comments stuck in the middle.
The Solution
But what if you don’t want your custom post types to show up below the Comments? It’s not logical from a content-entry perspective. The client will have to hunt for them.
More Google Fu revealed this answer on Stack Exchange, reaffirmed by the Codex entry on menu_order
:
add_filter('custom_menu_order', 'my_custom_menu_order'); add_filter('menu_order', 'my_custom_menu_order'); function my_custom_menu_order($menu_ord) { if (!$menu_ord) return true; return array( 'index.php', // the dashboard link 'edit.php?post_type=custom_post_type', 'edit.php?post_type=page', 'edit.php' // posts // add anything else you want, just get the url ); }
This worked like a charm. My final code in functions.php ended up like this:
// REARRANGE ADMIN MENU ORDER add_filter('custom_menu_order', 'my_custom_menu_order'); add_filter('menu_order', 'my_custom_menu_order'); function my_custom_menu_order($menu_ord) { if (!$menu_ord) return true; return array( 'index.php', // the dashboard link 'edit.php?post_type=yld_agent', 'edit.php?post_type=yld_career', 'edit.php?post_type=yld_case_study', 'edit.php?post_type=yld_daily_word', 'edit.php?post_type=yld_writers_corner', 'edit.php?post_type=page', 'edit.php', // posts 'edit-comments.php' ); }
And here’s what the actual admin menu looks like now. Everything is in the right order, because I specified it that way manually in the function.
After all the frustration I experienced, I will definitely remember this particular issue with WordPress, but I thought I would post the solution here in case anyone else runs into the same problem.
Postscript 4/30/15
I realized that rather than putting the code to rearrange the menu into functions.php
, I should add it to my post-types.php
plugin file, because I only want to rearrange the menu if the post types have been registered.
I’ve been bitten by this as well. I love this writeup. Very helpful!
I have the same problem. While this looks like a great solution, it has no impact on my admin menu. How would you go about debugging?
I’d first check to see whether you have a plugin installed that modifies the admin menu, because that could interfere. Also, if your custom post types are created by a plugin (or several), they may have a menu position specified already.
After 2 years from writing this article, it’s still helpful and relevant. I have spent the last 24 hours trying to solve this problem and finally stumbled upon your article.
Thank you very much.
You’re very welcome, Hassan. I write these tutorials so that people (including me, since I forget stuff) can solve problems faster.