When editing one of my custom post types I want to be able to list all entries by a custom field instead of the date they are published (which, for a custom post type probably isn’t relevant). I got a lead from the comments of a blog post about custom post types and the author said it was possible and that he even made it so you could click on the column names for a custom sort. He mentioned the posts_orderby
function which I noted in my own comments but now I can find the blog post anymore. Any suggestions? I saw one solution that used
add_action('wp', 'check_page');
And the check_page
function used add_filter
to change the query but I’m pretty sure it would only work in the theme files, not in the admin area.
As you can probably imagine by the lack of answers provided, the solution is not exactly trivial. What I’ve done is create a somewhat self-contained example that assumes a custom post type of “
movie
” and custom field key of “Genre“.Disclaimer: this works with WP3.0 but I can’t be sure it will work with earlier versions.
You basically need to hook two (2) hooks to make it work and another two (2) to make it obvious and useful.
The first hook is ‘
restrict_manage_posts
‘ which lets you emit an HTML<select>
in the area above the list of posts where the “Bulk Actions” and “Show Dates” filters. The code provided will generate the “Sort by:” functionality as seen in this screen snippet:(source: mikeschinkel.com)
The code uses direct SQL because there is not a WordPress API function to provide the list of all meta_keys for a post types (sounds like a future trac ticket to me…) Anyway, here’s the code. Note that it grabs the post type from
$_GET
and validates to make sure it is both a valid post typepost_type_exists()
as well as being amovie
post type (those two checks are overkill but I did it to show you how if you don’t want to hard-code the post type.) Lastly I use thesortby
URL parameter as it doesn’t conflict with anything else in WordPress:The second required step is to use the
parse_query
hook that is called after WordPress decides one what query is should run but before it runs the query. Here we get to set values oforderby
andmeta_key
in the query’squery_var
array which are documented in the Codex in theorderby
parameter forquery_posts()
. We test to make sure that:is_admin()
),$pagenow=='edit.php'
),post_type
URL parameter equal tomovie
, andsortby
URL parameter and that it wasn’t passed a value of ‘None‘If all those tests pass we then set the
query_vars
(as documented here) tometa_value
and oursortby
value for ‘Genre‘:And that’s all you need to do; no “
posts_order
” or “wp
” hooks required! Of course you actually do need to do more; you need to add some columns on your page that lists the posts so you can actually see the values that it is sorting by otherwise the users will get mucho confused. So add amanage_{$post_type}_posts_columns
hook, in this casemanage_movie_posts_columns
. This hook gets passed the default array of columns and for simplicity I just replaced it with two standard columns; a checkbox (cb
) and a post name (title
). (You can inspectposts_columns
with aprint_r()
to see what else is available by default.)I decided to add a “Sorted By:” for when there is a
sortby
URL parameter and when it is notNone
:Finally we use the
manage_pages_custom_column
hook to actually display the value when there is a post of the appropriate post type and with the probably redundant test foris_admin()
and$pagenow=='edit.php'
. When there is asortby
URL parameter we extract the custom field value that is being sorted by an display it in our list. Here’s what it looks like (remember, this is test data so no comments from the peanut gallery on the movie classifications! :):(source: mikeschinkel.com)
And here is the code:
Note that this only picks up the first “Genre” for a
movie
, i.e. the first meta_value in the case of multiple values for a given key. But then again I’m not sure how it would work otherwise!And for those unfamiliar with where to put this code you can put it in a plugin or more likely for the newbie in the
functions.php
file in your current theme.How this helps.
As of WordPress 3.1 (I’m using the beta) columns can now be sortable via their titles.
The following post details how implement them.
http://scribu.net/wordpress/custom-sortable-columns.html
Here’s a simple solution:
Just replace YOUR POST TYPE and ‘your_custom_field’