Hello guys,
This is a follow-up for this thread: https://toolset.com/forums/topic/create-a-related-articles-list-at-the-end-of-single-page-cpt/
So we have a view that's filtered based on the Tag of the page where the view is displayed.
It works well when we have the actual relationships configured but we'd like to make sure there is always 4 posts displayed, even if no tags are configured.
So for example, if there are only 2 posts with the same Tags, the view would display those and two other random Glossary Term and if there are no posts with a Tags relation then it would just display 4 random Glossary Terms.
Is there a way to do that?
Thank you!
Hi, there's not an easy way to accomplish this from wp-admin, but we do offer a PHP API that can be used to modify the result set on-the-fly based on the number of returned results. The API is called wpv_filter_query_post_process, and we have documentation available here: https://toolset.com/documentation/programmer-reference/views-filters/#wpv_filter_query_post_process
Here's a commented example of this API in use to ensure that at least 1 post is always returned:
add_filter( 'wpv_filter_query_post_process', 'tssupp_modify_empty_query', 10, 3 );
function tssupp_modify_empty_query( $query, $view_settings, $view_id ) {
if ( empty( $query->posts ) ) { // if the query found no posts
$default_post = get_post(1); // get the post with ID equal to 1
$query->posts = array( $default_post ); // add the default post to the posts result array
$query->found_posts = 1; // modify the count of found posts
$query->post_count = 1; // modify the count of displayed posts
}
return $query;
}
I'm not sure of your level of PHP knowledge, so let me know if you need more guidance on customizing this code for your needs.
Hey Christian,
Thanks for the link and example.
I'm guessing this would go in our child-theme functions.php, correct?
The example you provided is rather straightforward but what if we don't want specific posts (random glossary terms) and we'd like to keep the queried posts, if any found and there's less than 4?
I'm not entirely sure how I would merge, let's say for example, the first two posts returned that had a matching Tag with two other random posts.
Would something like that work?
add_filter( 'wpv_filter_query_post_process', 'nh_modify_related_gt_query, 10, 3 );
function nh_modify_related_gt_query( $query, $view_settings, $view_id ) {
if( $view_id = '22313' ) { // Applies to "Related Glossary Terms (4)" view
if ( sizeof( $query->posts ) < 4 ) { // if the query has less than 4 related terms
$fillsize = 4 - sizeof( $query->posts )
// Do something to query $fillsize random Glossary Term in var $randomqt
$query->posts = array( $randomqt ); // add the random posts at the end of the posts result array
$query->found_posts = 4; // modify the count of found posts
$query->post_count = 4; // modify the count of displayed posts
}
}
return $query;
}
I you could just provide some help for the random query part that would be fantastic!
Thank you!
Yes I think you're on the right track. Here's an example showing how to sort a query randomly:
https://wordpress.stackexchange.com/questions/115130/wp-query-random
$args = array(
'category_name' => 'cat1',
'posts_per_page' => 5,
'orderby' => 'rand',
);
$pc = new WP_Query( $args );
Info about ordering a WP_Query:
https://developer.wordpress.org/reference/classes/wp_query/#order-orderby-parameters
You should probably add a post__not_in clause, because you don't want duplicates. You would have to create an array of post IDs from the existing results, then pass that array into post__not_in. More information about WP_Query arguments here: https://developer.wordpress.org/reference/classes/wp_query/#post-page-parameters
Careful here - looks like this will overwrite the existing posts instead of appending to them:
$query->posts = array( $randomqt ); // add the random posts at the end of the posts result array
Maybe array_merge those arrays? https://www.php.net/manual/en/function.array-merge.php
Hey Christian,
Thanks again for the assistance.
So here's the code I've got but unfortunately it's causing an Error 500:
add_filter( 'wpv_filter_query_post_process', 'nh_modify_related_gt_query', 10, 3 );
function nh_modify_related_gt_query( $query, $view_settings, $view_id ) {
if( $view_id = '22313' ) { // Applies to "Related Glossary Terms (4)" view
if ( sizeof( $query->posts ) < 4 ) { // if the query has less than 4 related terms
$fillsize = 4 - sizeof( $query->posts );
$post_ids = wp_list_pluck( $query->posts, 'ID' );
$post_ids_string = implode( ',', $post_ids );
// Do something to query $fillsize random Glossary Term in var $randomqt
$args = array(
'post_type' => 'glossary',
'posts_per_page' => $fillsize,
'post__not_in' => $post_ids_string,
'orderby' => 'rand',
'no_found_rows' => true
);
$fillquery = new WP_Query( $args );
$filled_terms = array_merge($query->posts, $fillquery->posts);
wp_reset_postdata();
$query->posts = array( $filled_terms ); // add the random posts at the end of the posts result array
$query->found_posts = 4; // modify the count of found posts
$query->post_count = 4; // modify the count of displayed posts
}
}
return $query;
}
Here's the error:
PHP Fatal error: Uncaught Error: __clone method called on non-object in /.../wp-content/plugins/wp-views/embedded/inc/wpv.class.php:2453\nStack trace:\n#0 /.../wp-content/plugins/wp-views/embedded/inc/wpv.class.php(2055): WP_Views->render_view('22313', '39b96018ab57d3c...')\n#1 /.../wp-content/plugins/wp-views/embedded/inc/wpv.class.php(638): WP_Views->render_view_ex('22313', '39b96018ab57d3c...')\n#2 /.../wp-includes/shortcodes.php(325): WP_Views->short_tag_wpv_view(Array, '', 'wpv-view')\n#3 [internal function]: do_shortcode_tag(Array)\n#4 /.../wp-includes/shortcodes.php(199): preg_replace_callback('/\\\\[(\\\\[?)(easy\\\\-...', 'do_shortcode_ta...', '<style>@media a...')\n#5 /.../wp-includes/class-wp-hook.php(288): do_shortcode('<style>@media a...')\n#6 /.../wp-includes/plugin.php(206): WP_Hook->apply_filters('<style>@media a...', Array)\n#7 /.../wp in /.../wp-content/plugins/wp-views/embedded/inc/wpv.class.php on line 2453
Waiting for your feedback.
I changed the code slightly and now there no more Error 500 but the results are still empty...
EDIT: My bad, the error 500 is still there and the page glossary term page is broken.
Here's the new code:
add_filter( 'wpv_filter_query_post_process', 'nh_modify_related_gt_query', 10, 3 );
function nh_modify_related_gt_query( $query, $view_settings, $view_id ) {
if( $view_id = '22313' ) { // Applies to "Related Glossary Terms (4)" view
if ( sizeof( $query->posts ) < 4 ) { // if the query has less than 4 related terms
$fillsize = 4 - sizeof( $query->posts );
$post_ids = wp_list_pluck( $query->posts, 'ID' );
$post_ids_string = implode( ',', $post_ids );
// Do something to query $fillsize random Glossary Term in var $randomqt
$args = array(
'post_type' => 'glossary',
'posts_per_page' => $fillsize,
'post__not_in' => $post_ids_string,
'orderby' => 'rand',
'no_found_rows' => true
);
$fillquery = new WP_Query( $args );
$initposts[] = $query->posts;
$randposts[] = $fillquery->posts;
$filled_terms = array_merge($initposts, $randposts);
wp_reset_postdata();
$query->posts = array( $filled_terms ); // add the random posts at the end of the posts result array
$query->found_posts = 4; // modify the count of found posts
$query->post_count = 4; // modify the count of displayed posts
}
}
return $query;
}
Probably something to do with how the custom query is built...
Waiting for your feedback!
The value for post__not_in should be an array, not a comma-separated string. A comma-separated string will break the main $args array syntax.
'post__not_in' => $post_ids_string,
You can just use $post_ids here, since it's the array of IDs.
You probably don't need the reset post data here, I would comment it out:
Main issue: the $filledterms variable is already an array, so there's no need to wrap it in another array:
$query->posts = array( $filled_terms );
Hey Christian,
Thanks for the cues, unfortunately I'm still getting the same error.
Here's the latest code tested:
add_filter( 'wpv_filter_query_post_process', 'nh_modify_related_gt_query', 10, 3 );
function nh_modify_related_gt_query( $query, $view_settings, $view_id ) {
if( $view_id = '22313' ) { // Applies to "Related Glossary Terms (4)" view
if ( sizeof( $query->posts ) < 4 ) { // if the query has less than 4 related terms
$fillsize = 4 - sizeof( $query->posts );
$post_ids = wp_list_pluck( $query->posts, 'ID' );
$args = array(
'post_type' => 'glossary',
'posts_per_page' => $fillsize,
'post__not_in' => $post_ids,
'orderby' => 'rand',
'no_found_rows' => true
);
$fillquery = new WP_Query( $args );
$initposts[] = $query->posts;
$randposts[] = $fillquery->posts;
$filled_terms = array_merge($initposts, $randposts);
//wp_reset_postdata();
$query->posts = $filled_terms; // add the random posts at the end of the posts result array
$query->found_posts = 4; // modify the count of found posts
$query->post_count = 4; // modify the count of displayed posts
}
}
return $query;
}
Thanks again for your help with this.
Waiting for your feedback!
Remove the bracket notation here. These are new variable assignments:
$initposts = $query->posts;
$randposts = $fillquery->posts;
Thanks for that Christian, no more errors!
However for some odd reason our archive is affected by the function.
The Glossary Terms archive (View ID 22253) is configured to loop through Taxonomy terms using a Taxonomy view (ID 22249) which loops through items with a child-post view (ID 22251).
So there's nowhere in the Archive the use of the view with the ID 22313, which is used to display 4 related Glossary Terms. Since the function is pretty much wrapped in a conditional to check for the view 22313 I'm not sure what's going on here.
Waiting for your feedback!
Hey Christian,
Looks like this was some sort of caching issue... I waited a bit and the Archive page returned to normal.
Thanks again for your help!