WP_Query orderby breaks when using AJAX?

I’m running in to a bit of a problem.

I have a function called get_press(), it retrieves newest press items. It is inside of a plugin:

Read More
class EWPress {
    function __construct()
    {
        load_plugin_textdomain( 'ew', flase, dirname( plugin_basename( __FILE__ ) ) . '/lang' );

        add_action( 'wp_enqueue_scripts', array( &$this, 'register_plugin_scripts' ) );

        // Add JS var ajaxurl to global namespace
        add_action( 'wp_head', array( &$this, 'add_ajax_library' ) );

        add_action( 'wp_ajax_get_press', array( &$this, 'get_press' ) );
        add_action( 'wp_ajax_nopriv_get_press', array( &$this, 'get_press' ) );

    }

    public function get_press()
    {
        $args = array(
            'status' => 'publish',
            'post_type' => 'press',
            'orderby' => 'meta_value',
            'meta_key' => 'press_date',
            'order' => 'DESC',
            'posts_per_page' => 2
        );

        $query = new WP_Query($args);
            return($query->posts);
            //echo json_encode($query->posts);
            //die();
    }
}

If I call this function directly in a template file via: echo EWPress::get_press() the output is completely fine:

Array
(
    [0] => WP_Post Object
        (
            [ID] => 229
            [post_author] => 1
            [post_date] => 2013-01-18 00:29:58
            [post_date_gmt] => 2013-01-18 00:29:58
            [post_content] => 
            [post_title] => Rundown
            [post_excerpt] => 
            [post_status] => publish
            [comment_status] => closed
            [ping_status] => closed
            [post_password] => 
            [post_name] => rundown
            [to_ping] => 
            [pinged] => 
            [post_modified] => 2013-01-18 00:29:58
            [post_modified_gmt] => 2013-01-18 00:29:58
            [post_content_filtered] => 
            [post_parent] => 0
            [guid] => http://site.com/?post_type=press&p=229
            [menu_order] => 0
            [post_type] => press
            [post_mime_type] => 
            [comment_count] => 0
            [filter] => raw
        )

    [1] => WP_Post Object
        (
            [ID] => 231
            [post_author] => 1
            [post_date] => 2013-01-18 00:44:35
            [post_date_gmt] => 2013-01-18 00:44:35
            [post_content] => 
            [post_title] => Clean Plates
            [post_excerpt] => 
            [post_status] => publish
            [comment_status] => closed
            [ping_status] => closed
            [post_password] => 
            [post_name] => clean-plates
            [to_ping] => 
            [pinged] => 
            [post_modified] => 2013-01-18 00:44:35
            [post_modified_gmt] => 2013-01-18 00:44:35
            [post_content_filtered] => 
            [post_parent] => 0
            [guid] => http://site.com/?post_type=press&p=231
            [menu_order] => 0
            [post_type] => press
            [post_mime_type] => 
            [comment_count] => 0
            [filter] => raw
        )

)

In order to make an AJAX request, I:

  • comment out the echo EWPress::get_press() on the template level
  • comment out the return $query->posts in the get_press() function
  • un-comment the echo json_encode($query->posts)
  • un-comment the die();

However, when I make the AJAX request to the SAME function the returned data is different (namely it is ignoring order = 'ASC' or 'DESC).

AJAX Function:

(function($) {
    $(document).ready(function(){
        $.ajax({
            url: ajaxurl,
            type: 'POST',
            dataType: 'json',
            data: {action: 'get_press'},
            complete: function(xhr, textStatus) {
                //
            },
            success: function(data, textStatus, xhr) {
                console.log(data);
            },
            error: function(xhr, textStatus, errorThrown) {
            //called when there is an error
            }
        });
    });
})(jQuery);

The console.log:

[Object, Object]
0: Object
    ID: 234
    comment_count: "0"
    comment_status: "closed"
    filter: "raw"
    guid: "http://site.com/?post_type=press&p=234"
    menu_order: 0
    ping_status: "closed"
    pinged: ""
    post_author: "1"
    post_content: ""
    post_content_filtered: ""
    post_date: "2013-01-18 02:33:41"
    post_date_gmt: "2013-01-18 02:33:41"
    post_excerpt: ""
    post_mime_type: ""
    post_modified: "2013-01-18 02:33:41"
    post_modified_gmt: "2013-01-18 02:33:41"
    post_name: "eater"
    post_parent: 0
    post_password: ""
    post_status: "publish"
    post_title: "Eater"
    post_type: "press"
    to_ping: ""
    __proto__: Object
1: Object
    ID: 231
    comment_count: "0"
    comment_status: "closed"
    filter: "raw"
    guid: "http://site.com/?post_type=press&p=231"
    menu_order: 0
    ping_status: "closed"
    pinged: ""
    post_author: "1"
    post_content: ""
    post_content_filtered: ""
    post_date: "2013-01-18 00:44:35"
    post_date_gmt: "2013-01-18 00:44:35"
    post_excerpt: ""
    post_mime_type: ""
    post_modified: "2013-01-18 00:44:35"
    post_modified_gmt: "2013-01-18 00:44:35"
    post_name: "clean-plates"
    post_parent: 0
    post_password: ""
    post_status: "publish"
    post_title: "Clean Plates"
    post_type: "press"
    to_ping: ""
    __proto__: Object
length: 2
__proto__: Array[0]

Does anyone know why this would be happening?

Related posts

Leave a Reply

4 comments

  1. I believe Milo is right, it’s probably a filter affecting this. Ajax requests look like admin requests (that is, is_admin() returns true), so it’s possible that something is checking if is_admin() and adding the filter in those cases.

    You can set 'suppress_filters' => true in your args array and it will probably work. Note that doing so can prevent a query from being cached, or prevent plugins from doing what they need to with a query. It’s possible that this may not affect you, but still something to keep in mind.

  2. pre_get_posts actions can also affect query params.
    You can try adding remove_all_actions('pre_get_posts'); to your ajax handler before WP_Query.
    If this helps, check actions with

    global $wp_filter
    print_r($wp_filter['pre_get_posts']);
    

    to see what can break WP_Query behavior.
    In my case it was Simple Custom Post Order which affected WP_Query in ajax mode.

  3. For some odd reason WP_Query is the culprit behind this issue.

    When doing an AJAX request to a function that returns a WP_Query object, the $query->posts object completely ignores any of the arguments supplied in $args.

    A simple work around was to use get_posts instead with the same $args as with the WP_Query

    One unfortunate drawback of this method is the loss of nice features of a WP_query object, such as $query->max_num_pages.