If I understand well you want to show the last post (one post) from one of the 3 post types you have, using a dynamic url like http://example.com/latest
.
First of all lets add a filter to 'do_parse_request'
filter:
add_filter( 'do_parse_request', function( $bool, WP $wp ) {
$home_path = trim( parse_url( home_url(), PHP_URL_PATH ), "https://wordpress.stackexchange.com/" );
$path = substr( trim( add_query_arg( array() ), "https://wordpress.stackexchange.com/" ), strlen( $home_path ) );
if ( $path === 'latest' ) { // change 'latest' to anything else to change the url
$wp->query_vars = array(
'posts_per_page' => 1, // if you want more than one post change this
'post_type' => array(
'post',
'another_cpy', // this should be your CPT name
'yet_another_cpt' // this should be your CPT name
)
);
$wp->is_latests = true;
return false; // stop WordPress parsing request
}
$wp->is_latests = false;
return $bool;
}, 0, 2);
Using previous code when you visit a page like http://example.com/latest
WordPress will pick the last post from one of the 3 CPT, however you have no control on the template (index.php
will be used).
However a simple filter to 'template_include'
allows to choose the template:
add_filter( 'template_include', function( $template ) {
global $wp;
if ( $wp->is_latests ) {
// change the name of the templates you want to use.
// If none of the files is found in your theme folder, than index.php will be used
$locate_template = locate_template( array( 'latest.php', 'single.php' ) );
if ( ! empty( $locate_template ) ) {
$template = $locate_template;
}
}
return $template;
} );
That’s all. Note that:
- to view the page only one db query is required
- you do not need to create a page, nor a page template for the scope
- no rewrite rule is involved
Edit
If you want more than one post, let’s say 3, and you want the last post for each CPT (like the answer by @DrewAPicture does) you can do it without running 3 separate queries.
First of all change 'posts_per_page' => 1
to 'posts_per_page' => 3
in the code above, after that add a filter to 'posts_groupby_request'
:
add_filter( 'posts_groupby_request', function( $groupby, $query ) {
global $wp;
if ( ! is_admin() && $query->is_main_query() && $wp->is_latests ) {
$groupby = "{$GLOBALS['wpdb']->posts}.post_type";
}
return $groupby;
}, PHP_INT_MAX, 2);