Custom Posts Order in WordPress

WordPress in its native environment doesn’t provide any option to change the default sorting rule which means that the latest post is always displayed as the first one etc. It’s like: “Dear users, you will forever have your posts sorted the way we have determined or just go screw yourself.”

It seems like there’s not a single person on the whole damn Internet who could give you a simple answer as if it were a quantum science. It’s not.

I don’t care about plugins that would allow me to drag & drop particular posts and thus change their order. I wanted something nice and clean that would work automatically. Neither do I care about tutorials that make me spend a couple of sleepless nights delving into a dozen subtopics and becoming a guru coder with my hair tousled.

Let me share with you a solution that worked out perfectly for what I needed. I don’t claim it’s a total breeze but it’s not necessarily beyond comprehension and it’s the easiest way I can think of given the current WordPress limitations.

 

1. When you go to a particular post in your administration (under Posts –> All Posts –> any particular post) there’s a tab called ‘Screen Options’ on the top that gets ejected upon clicking. Then there’s a check box next to ‘Custom Fields’ which is what you need to check first. (It will stay checked from now on for all other posts as well.)

2. Then scroll all the way down and you’ll see a ‘Custom Fields’ section with two columns. Type ‘myordernum’ (without quotes) in the Name field. The Value field will now be reserved for a custom order number, meaning it’s up to you to determine where exactly this particular post is going to be placed within a list of posts. Insert your desired order number into the ‘Value’ field and hit the ‘Add Custom Field’ button below. 1 will sit before 2 etc. (You will as well be able to easily revert the order if you like to.) Don’t worry, I will explain in a short while how to make it work for pages, categories or a homepage. But it’s not that easy. We won’t avoid some coding in the next steps anyway.

3. Now go to Appearance –> Editor and click on the functions.php link in the right panel (it is located under ‘Theme Functions’ subheading).1

Make sure you have clicked on the functions.php and not on anything else. You should see the name of the chosen file as a headline on the top, it will say something like this: “Your theme name: Theme Functions (functions.php)”. I strongly recommend that you make a backup of the original functions.php file before you proceed. If you happen to mess something up you can always replace the file with the original one via FTP. The file is located in /wp-content/themes/your-theme-name/.

4. Scroll all the way down and copy-paste the following code at the end of the functions.php file. The following piece of code will sort all the posts within a certain category (‘your_category_name’) according to the order numbers you have inserted into the ‘Custom Field –> Value’ in step 2.

/* Will sort posts within the specified category according to my order numbers */
function custompostorder_cat( $query ){
  if ( $query->is_main_query() && is_category( 'your_category_name' ) ){
  $query->set( 'orderby', 'meta_value_num' );
  $query->set( 'meta_key', 'myordernum' );
  $query->set( 'order' , 'ASC' );
  }
 }
add_action( 'pre_get_posts' , 'custompostorder_cat' );

Make sure you have replaced the ‘your_category_name’ with the proper name of your own category otherwise it won’t work. Preferably, use a ‘slug’ name (see further explanation below). Or you can delete everything within the brackets if you want this to apply to all the categories (see the detailed explanation on the code below).
CAUTION: After applying the above code you will not be able to see any posts listed under the given category unless they are assigned the Custom Field Value!
In other words, you will first have to insert order numbers into all the posts within the said category in order to have them displayed under the category list on your website. You could still see them on a homepage if it’s set up to show the latest posts but not in the respective category list. (Note: You can’t copy-paste the code into the ‘Custom (Additional) CSS’ box within your theme customization settings. It’s PHP, not CSS. You have to put it into the functions.php.)

5. Now comes the ‘tweaking’ part and an explanation so that you can adjust this to your liking. I have used the above example because it’s categories what I am concerned about and what I use as entries in my main menu but you can obviously do the same not only for categories but for a particular page (or for all pages) and also for a homepage, you just need to know how to specify this in the code. Here are the important parts:

‘your_category_name’ – Once again, this is a name of the category you’d like to apply the rule to. I suggest that you use a ‘slug’ name (URL-friendly version of the name). But it should work with the full names too. You can find a respective slug name under Posts –> Categories –> then there’s a ‘Slug’ column.

is_category() – If you leave the category unspecified like this (you have to keep the brackets) then the rule is going to be applied across all the categories on your website. But remember that in such case you will no longer be able to see any posts under any category list on your website if it doesn’t include the ‘Custom Field –> Value’!
Now, let’s say you want to apply your sorting rule to a page instead of a category. You will do that by simply replacing the is_category() function with is_page() and specifying the name of the page like this, for instance: is_page( ‘about-me’ ). Obviously, replace the ‘about-me’ part with a (slug) name of the desired page.
And if you want to affect your homepage then just replace the is_category() function with is_home().

If you’d like to apply the same rule to a number of specific categories instead of just one then you can list them via an ‘array’ function like this (be careful about a proper usage of the brackets, there are a bunch of them):

/* Will sort posts within the specified categories according to my order numbers */
function custompostorder_cat( $query ){
if ( $query->is_main_query() && is_category( array( 'category1', 'category2' ) ) ){
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'meta_key', 'myordernum' );
$query->set( 'order' , 'ASC' );
}
}
add_action( 'pre_get_posts' , 'custompostorder_cat' );

Remember that you have to replace the ‘category1’, ‘category2’ parts with the actual names of the desired categories.

Now, let’s say you’d like to apply the rule to multiple sections of the website at the same time (like for instance for categories and homepage). Note that you’d not be able to just join the functions by logical parameters (‘||’, ‘or’ etc.) in a single line of the PHP code. You could mess it up. (It might seem to be working but, for instance, the menu might not be properly displayed every time etc.) It’s therefore recommended that you add the whole additional piece of code. The following example shows how to apply the same rule to your homepage. This piece of code is meant to be added to the one you have used previously for a different section of your website. (It’s actually not my case ’cause I want the posts on my homepage to be sorted in a usual way. But I’m stating this in here for the sake of integrity.)

/* Will sort posts on home page according to my order numbers */
function custompostorder_home( $query ){
if ( $query->is_main_query() && is_home() ){
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'meta_key', 'myordernum' );
$query->set( 'order' , 'ASC' );
}
}
add_action( 'pre_get_posts' , 'custompostorder_home' );

CAUTION: Again, after applying the above code you will not be able to see any posts on your homepage unless they are assigned the ‘Custom Field ->> Value’! (Except for a sticky post.)

‘meta_value_num’ – You don’t need to worry about this. It represents your own custom order numbers you’ve inserted into the ‘Custom Field –> Value’ for each post and says to the ‘orderby’ argument that you want the posts to be sorted by those values. (Note that in most tutorials there’s just ‘meta_value’ parameter used which would, however, work just as a text string, not as a number we’d rather have in this case, and therefore would require that you define your order numbers as ’01, 02, etc.’ or ’001, 002, etc.’ instead of just ’1, 2, etc.’ in order to make them work beyond 9. Either way, you essentially can’t go wrong with typing the numbers as ‘001, 002, etc.’, just to make sure.)
My tip is to assign the posts with decimal order numbers (010, 020, etc.) and thus keep some room if there arises a need any later to shove a new post in between the old ones.

‘ASC’ – This determines that you want to sort the posts in ascending order. (You can simply revert the order by replacing the parameter with ‘DESC’.)

(Note: You’ll need to add the code to your functions.php over again every time you have updated your theme unless you’re using a child theme or My Custom Functions plugin.)

 


1. [If you can’t see the functions.php file within the list you may be using a child theme that doesn’t include it. In such case I strongly recommend that you create the file manually and not modify the parent theme!
There are two main reasons why you might want to create the functions.php file for your child theme before you move on to another step. Firstly, any interference into your parent theme will result in your child theme basically missing its main point. The point being that whenever your parent theme gets updated your customization will stay unaffected. And secondly, an absence of the said file within your child theme indicates that it uses an old ‘@import’ method which is not best for performance. However, if you for some reason do wish to proceed with affecting your parent theme then you’ll first need to select its name in the upper right part of the screen and hit the ‘Select’ button. Then you’ll be able to see the functions.php file of your parent theme.
One of the best ways to go about this is install a plugin that will allow you to add custom PHP code without affecting your parent theme and then just go to Appearance –> Custom Functions and copy-paste the code in there instead of editing functions.php in Appearance –> Editor.]

Leave a Reply

Your email address will not be published. Required fields are marked *