the_title() and the_permalink() won’t work on AJAX calls

I’ve run into a strange problem.

I have a custom loop built with get_posts that works fine when loading the page normally:

Read More
<?php
    $rows = get_posts(array(
        'post_type'     => 'drinks', 
        'numberposts'   => -1
    ));
?>

<?php foreach ($rows as $post) : setup_postdata($post) ?>
    <?php the_post_thumbnail() ?>
    <h3><?php the_title() ?></h3>
    <?php the_content() ?>
    <?php the_permalink() ?>
<?php endforeach; wp_reset_postdata() ?>

That code sits inside its own template called “drinks.php”.

Now I’ve set up an AJAX function/URL to fetch this template using jQuery:

add_action('wp_ajax_h5b_get_user_drinks', 'h5b_ajax_get_user_drinks');
add_action('wp_ajax_nopriv_h5b_get_user_drinks', 'h5b_ajax_get_user_drinks');

function h5b_ajax_get_user_drinks () {
    include 'drinks.php';
    die;
}

However, when I fetch it with AJAX it seems that neither the_title(), the_post_thumbnail() or the_permalink() work. the_content() seems to work fine though.

If I var_dump($post) inside my loop it has all the data it should (like title, guid etc).

How can this be?

Related posts

Leave a Reply

2 comments

  1. You need to delcare $post as global, try:

     global $post;
    <?php foreach ($rows as $post) : setup_postdata($post) ?>
        <?php the_post_thumbnail() ?>
        <h3><?php the_title() ?></h3>
        <?php the_content() ?>
        <?php the_permalink() ?>
    <?php endforeach; wp_reset_postdata() ?>
    

    Most of these functions can only work (and all of them when used without parameters) inside the Loop. What this means is that the global $post points to the appropriate post.

    Note: setup_postdata($post) doesn’t do this! Hence you need to manually declare global $post.

    The accepted answer, which offers perhaps a more aesthetic answer uses get_template_part(), which in turn calls load_template() via (locate_template()). Looking the source – this declares $post variable as a global, from the comments:

    The globals are set up for the template file to ensure that the WordPress environment is available from within the function.

    Hence it works :).