$post is undefined in wordpress loop [ajax]

The question:

I’m currently working on calling the next page of posts through ajax. I’m making my request with jQuery, building a custom query in my php handler function, looping through it and then sending back the HTML. This is my loop:

  $args = $_REQUEST['query'];

  $request_query = new WP_Query($args);

  if ($request_query->have_posts()) {
      while ($request_query->have_posts()) {
          $request_query->the_post();

          if ($post->post_type == 'foo') {
              get_template_part('/parts/thumbnail-templates/foo');
          } else if ($post->post_type == 'bar') {
              get_template_part('/parts/thumbnail-templates/bar');
          } else {
              get_template_part('/parts/thumbnail-templates/generic');
          }
      }
  }

Everything works correctly and the loop runs as expected, except that I get an error that states $post is undefined, so my two ifs fail, as well as some lines inside my templates which call metadata like this $post->the_meta_key.

I figure the reason this happens is that there’s some other wp magic that runs behind the scenes and makes $post available in template files, but not in ajax. Hence, I added global $post; just before my if statements and now it works as expected.

The question

Is it okay to call global $post; inside the loop in ajax or is there a better way to access the current post object? Also, if there are any general best practice suggestions for changes in my approach, please let me know.

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

Is it okay to call global $post; inside the loop in ajax or is there a better way to access the current post object?

I’d do it outside the loop but in the same scope to avoid duplication, but otherwise the answer is:

If it works, then it works, don’t stress about it, there is no canonical one way to rule them all for this.

global $post; works, and there is another option of $post = get_post(); but it’s rare. Most people just do global $post; out of habit.

You can also avoid it entirely by doing this:

if ( get_post_type() === 'foo' ) {

I figure the reason this happens is that there’s some other wp magic that runs behind the scenes and makes $post available in template files, but not in ajax. Hence, I added global $post; just before my if statements and now it works as expected.

Nope, this theory is incorrect, post loops work the same in AJAX handlers

$args = $_REQUEST['query'];
$request_query = new WP_Query($args);

This should be considered a major security hole, as now anybody can query for anything, and they can trigger super expensive queries that will hammer your database aka resource exhaustion attacks. Whitelist the arguments you allow and their valid values!


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment