I’m trying to create an advanced WordPress page that shows the regular content, plus a second section on the same page that shows the latest posts from X tag. For example, a page is created about “cats”, has pictures, content, etc. Afterwords, I’d like to display the last X posts tagged with “cats”. Is that possible without using plugins, and without creating a custom page template for every page?
Perhaps it’s doable with the custom fields feature and multiple loops. E.g. get X amount of posts from a custom field with the value “cats”. I’ve been struggling with it for a while now, can can’t seem to find a solution that doesn’t involve create a template for every single page.
Thanks!
This should do the job. It’ll check for posts that have been tagged with the title of the current page. There’s no need to use if (have_posts()):
on a page template: if the template is called it will be because there is a post 🙂
<div class="page-loop">
<?php
while (have_posts()) : the_post();
$page_title = strtolower(get_the_title());
the_title('<h1>','</h1>');
?>
<p><?php the_content(); ?><p>
<?php endwhile;?>
</div>
<!-- Get the most recent post that has been tagged with the page title -->
<div class="related-posts">
<?php
$args = array(
'tag' => $page_title,
'posts_per_page' => 1,
);
$query = new WP_Query($args);
if ($query->have_posts()) :
while ($query->have_posts()) : $query->the_post();
the_title('<h1>','</h1>');
?>
<p><?php the_content(); ?><p>
<?php endwhile; else: ?>
<p>Sorry, no posts with this tag!</p>
<?php endif; wp_reset_query(); ?>
</div>
If you’d rather use custom meta to add the ‘tag’ to the page (instead of just using the title) you could add a custom meta box to the page like so. Add the following code to your functions.php (nb: this will add the meta box to all pages)
/** register the meta box */
function my_theme_add_meta_boxes() {
global $post;
add_meta_box(
'my-theme-meta',
'Choose a tag',
'my_theme_print_page_meta',
'page',
'normal',
'high'
);
}
add_action('add_meta_boxes', 'my_theme_add_meta_boxes');
/** Add extra meta to the page */
function my_theme_print_page_meta() {
global $post;
$page_tags = get_post_meta($post->ID, '_page-tags', true);
?>
<label for="page-tags">Add a 'tag'</label>
<input type="text" class="page-tags" name="page-tags" value="<?php echo esc_attr($page_tags); ?>" />
<?php
}
/** Save post meta */
function my_theme_save_custom_meta() {
global $post;
// Stops WP from clearing post meta when autosaving
if( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
return $post->ID;
}
if (isset($_POST['page-tags'])) {
$clean = sanitize_text_field($_POST['page-tags']);
update_post_meta($post->ID, '_page-tags', $clean);
}
}
add_action('save_post', 'my_theme_save_custom_meta');
Then your page.php code could look like this:
<div class="page-loop">
<?php
while (have_posts()) : the_post();
$page_tags = get_post_meta($post->ID, '_page-tags', true);
the_title('<h1>','</h1>');
?>
<p><?php the_content(); ?><p>
<?php endwhile;?>
</div>
<?php if ($page_tags): ?>
<!-- Get the most recent post that has been tagged with the page title -->
<div class="related-posts">
<?php
$args = array(
'tag' => $page_tags,
'posts_per_page' => 1,
);
$query = new WP_Query($args);
if ($query->have_posts()) :
while ($query->have_posts()) : $query->the_post();
the_title('<h1>','</h1>');
?>
<p><?php the_content(); ?><p>
<?php endwhile; else: ?>
<p>Sorry, no posts with this tag!</p>
<?php endif; wp_reset_query(); ?>
</div>
<?php endif; // There are 'page tags' ?>