Occasionally we have 2¢ to add

Order Posts by Custom Key revisited

I’ve gotten quite a few questions about how to get this to work on a specific page, or only within a specific category. I actually had the same issue when building the script originally. The trick is that you can’t just use the conditional tags in the functions page. At that point, it’s already too late because the queries have already been run. You have to create a function and then run it as a filter on one of the early WordPress initializing functions. I chose the wp() function. Here is my revised code (nearly straight from the client’s site).

add_action('wp', 'check_page');
function check_page () {
	if (is_page('The Page Name')) {
		add_filter('get_previous_post_sort', 'sort_it');
		add_filter('get_next_post_sort', 'sort_it');
		add_filter('posts_orderby', 'sort_it' );
		add_filter('posts_join', 'join_it' );
		add_filter('posts_where', 'where_it' );

		function sort_it () {
			global $wpdb;

			return " $wpdb->postmeta.meta_value DESC ";
		}

		function join_it( $join ) {
			global $wpdb;

			$join .= " LEFT JOIN $wpdb->postmeta ON($wpdb->posts.ID = $wpdb->postmeta.post_id) ";

		  return $join;
		}

		function where_it( $where ) {
			global $wpdb;
			$where .= "AND $wpdb->postmeta.meta_key = 'Price' ";

		  return $where;
		}
	}
}

In our case, we were sorting by the “Price” meta key and we were sorting from highest to lowest price. I hope this helps clear things up. Thanks to Paul Gray for sending us an email asking for some clarification.

This entry was posted in Code Snippits, Tips and tagged , , , , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

15 Comments

  1. Posted February 23, 2009 at 11:47 am | Permalink

    This really helps in many ways! Thanks for posting it!

  2. Posted February 23, 2009 at 11:51 am | Permalink

    @sc0ttkclark – You got it. Glad we could help.

  3. nate
    Posted March 2, 2009 at 4:01 pm | Permalink

    This is exactly what I’m looking for – one question on useage – when running check page (is_page), how do you trigger it to run on a page running custom posts? Do you simple enter a category name or number or something more involved than that?

  4. Posted March 3, 2009 at 9:22 am | Permalink

    @nate – You would use this in the exact same way. We’re checking what page we’re requesting by hooking into the wp action. We then add our filters on the query if it’s the right page. So, in our example above, you’d simply put your custom page’s name in place of “The Page Name.”

    Make sense?

  5. jean
    Posted March 8, 2009 at 12:35 am | Permalink

    Hi, I think your solution is exactly what I was looking for but being a php nono I am having trouble making it work. I would very much appreciate a little help !
    I have 2 custom fields 1 called “special” with value “1″ to retrieve posts ,this works fine using code found on WP Codex. I would like to list them on page sorted ASC using a 2nd custom field called “tri” with value from 1 to XX. I have found the theme function.php file and pasted code after changing page name but how do I wrap the code with php tags
    all I get is php errors
    do I put php tags before “add_action….” ?
    or just after “add_action….” ?
    all I get is php errors again
    What am I doing wrong ???
    Thanks for help

  6. Posted March 9, 2009 at 9:26 am | Permalink

    @jean – Yes, you definitely have to wrap the php code in php tags “<?php” and “?>” respectively in the functions.php file. Were you able to get the query sorted out? Seems like it would be as simple as adding a a condition to the where_it function. I’m not sure why you’re doing that though. Seems like it would be much easier to assign posts to a certain category and just call those posts in via the query_posts(‘&cat=category-id-here’). You can still use our sorting functions using this method. In fact, this is how we do it on our client’s site.

  7. wami
    Posted March 18, 2009 at 6:54 am | Permalink

    First, thank you so much for this code, it´s exactly what I´m missing so long.

    I´ve copied the code above and put it in my functions.php, but now when I open my homepage I get an php-error:

    Parse error: syntax error, unexpected T_FUNCTION

    Have you an idea why?

    kr

    Michael

  8. Posted March 18, 2009 at 5:41 pm | Permalink

    @wami – It’s hard to tell without seeing what you’re doing exactly. That error is usually caused by not finishing a line with a semi-color, closing parenthesis in a function or closing a brace in defining or specifying an array. Take a look just above the line that it’s erroring out at something like that. If you don’t find anything, feel free to contact me through out need help page and I can take a look for you.

  9. mezzomind
    Posted April 6, 2009 at 12:59 am | Permalink

    Thanks for this!

    I did run into a small issue that was driving me crazy for about 10 minutes. I was getting an error about the ‘wpdb’ class not being able to be converted to a string. After some quick research into the ‘wpdb’ class and its use I realized the problem.

    The source code has encoded ‘>’ characters, %gt; which inside of php quotes is just read as string content. So instead of $wpdb->postmeta we have $wpdb->postmeta, which was the source of my error. Anyone copying and pasting this code could encounter this issue as well.

    Good Day,
    Andrew

  10. Posted April 6, 2009 at 4:13 pm | Permalink

    @mezzomind – I didn’t realize that it copy/pasted like that. That must be a function of the plugin we’re using to output our source code. I’ll see what I can do to fix this.

  11. nowimproved
    Posted July 28, 2009 at 4:02 pm | Permalink

    So how do you fix this copy and paste issue?

  12. Posted July 28, 2009 at 9:57 pm | Permalink

    @nowimproved – you need to find all instances of “&gt;” and replace them with “>”

  13. nowimproved
    Posted July 29, 2009 at 9:44 am | Permalink

    Thank you , that worked great.

    Now my only problem is , I replaced Price with startdate. I am trying to sort by the custom fields july 24 june 4 dec 9 etc.. Is this possible?

  14. Posted August 18, 2009 at 10:11 am | Permalink

    @nowimproved – You’d have to do some MySQL magic and convert those strings to dates and compare that way. If you’re trying to order by date thought, why not just use the built in date ordering? You could just post each entry on the date you’re trying to order by.

  15. Posted March 11, 2011 at 9:08 am | Permalink

    Hello,
    Can anyone help me? I have been up for a day and half trying figure this out. I am a newbie so i’m totally self taught. with that being said can someone tell me how get this code to work? I would like it so that once the event date has passed the even no longer shows.I want the events to be sorted by the custom event_date field and then not be shown once the event_date has passed.
    I enter the event_date format 03/14/2011
    Below is the code is have. I’m using it and a function for all the archive category pages. Could someone please please help me?
    —————————————–
    add_filter(‘posts_join’, ‘new_join’ );
    function new_join($pjoin){
    if(is_category()){
    global $wpdb;
    $pjoin .= “LEFT JOIN (
    SELECT *
    FROM $wpdb->postmeta
    WHERE meta_key = ‘event_date’
    AND STR_TO_DATE(meta_value,’%m/%d/%Y %H:%i:%s’) >= CURDATE() ) AS metasort
    ON $wpdb->posts.ID = metasort.post_id”;
    }
    return ($pjoin);
    }

    add_filter(‘posts_orderby’, ‘new_order’ );
    function new_order( $orderby ){
    global $wpdb;
    if(is_category()){
    $orderby = “metasort.meta_value, ‘%m/%d/%Y %H:%i:%s’ ASC”;
    }

    return $orderby;
    }

2 Trackbacks

  1. [...] Order Posts by Custom Key Revisited [...]

  2. [...] first in this post “6Ways to Create Custom Write Panels in WordPress“.  Then, use the sort function as referenced in esdev.net’s gameplan when outputting the list of events in your theme organized by custom [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>