Archived topic
Mixed Content Templates
8 replies · Started by Aaron on June 1, 2022
I do have custom post types and two content templates for use on their archive pages. Could you imagine or provide a code snippet I can use to display different content templates in a search results page based on the post type?
Maybe something like:
if (have_posts()) {
while (have_posts()) {
the_post();
get_template_part('template-parts/content', get_post_type());
}
but for gp's content templates
Hi Aaron,
How are you implementing your Search functionality?
Do you have a custom Search form that includes the Post type in the search query?
You can use filter: generate_block_element_display to filter which Content Template would display on a Search page.
For instance, a simple example is this code:
add_filter( 'generate_block_element_display', function( $display, $element_id ) {
if ( is_search() ) {
if ( 123 === $element_id && 'cpt-1-slug' === get_search_query() ) {
$display = true;
} else if ( 456 === $element_id && 'cpt-2-slug' === get_search_query() ) {
$display = true;
}
}
return $display;
}, 15, 2 );
Adding PHP reference: https://docs.generatepress.com/article/adding-php/#code-snippets
If the search query is cpt-1-slug, Block Element - Content Template would be the one displayed. Kindly not that no location should be set in the Display rules of the Block Element.
You could expound this code to check the search query through get_search_query(), and conditionally display a Content Element depending on the query.
Hope this helps!
Hi Fernando,
thanks for the reply.
How are you implementing your Search functionality?
I am using generatepress default search form enabled via the customizer Layout>Primary Navigation>Navigation Search: Enable and the default search results page template themes/generatepress/search.php
Do you have a custom Search form that includes the Post type in the search query?
Nope, how would I do this? I guess I need this for your snippet to work?
You can use filter: generate_block_element_display
Does this differ from https://docs.generatepress.com/article/generate_element_display/ ? I can't find this filter listed in your docs.
I removed all display conditions and tried to implement your snippet, but I failed. I think it should not be based on the query string the user entered, since the user don't search for a cpt slug rather than actual content. But maybe I got you wrong?
This is what I tired:
// Use different search results templates based on post type
add_filter('generate_block_element_display', function ($display, $element_id) {
if (is_search()) {
// if post type is charityscreening display the charityscreening element template
if (13802 === $element_id && 'charityscreening' === get_post_type()) {
$display = true;
// if post type is movie display the movie element template
} elseif (5666 === $element_id && 'movie' === get_post_type()) {
$display = true;
// if post type is not movie nor charityscreening display the default element template
} elseif (11166 === $element_id && !('movie' === get_post_type() || 'charityscreening' === get_post_type())) {
$display = true;
}
}
return $display;
}, 15, 2);
Now all results are using the template that was given on the first hit, and it is not chosen dynamically.
For instance, here’s an HTML for a CPT called Games:
<div>
<h3>Search Products</h3>
<form role="search" action="" method="get" id="searchform">
<input type="text" name="s" placeholder="Search"/>
<input type="hidden" name="post_type" value="Games" />
<input type="submit" alt="Search" value="Search" />
</form>
</div>
Then, I can filter the search results to show only Game results or another CPT for instance like this:
function my_search_filter($query)
{
$post_type = get_query_var('post_type');
if ($query->is_search && !is_admin()) {
if ( 'Game' === $post_type ) {
$query->set('post_type', ['Game']);
} else if ( 'cpt-2-slug' === $post_type ) {
$query->set('post_type', ['cpt-2-slug']);
}
}
return $query;
}
add_filter('pre_get_posts', 'my_search_filter');
Lastly, you can filter which Block element should appear:
add_filter( 'generate_block_element_display', function( $display, $element_id ) {
if ( is_search() ) {
$post_type = get_query_var('post_type');
if ( 394980 === $element_id && 'Game' === $post_type ) {
$display = true;
} else if ( 456 === $element_id && 'cpt-2-slug' === $post_type ) {
$display = true;
}
}
return $display;
}, 15, 2 );
You can also modify the HTML code to have something like a dropdown to select the Post type.
Hope this clarifies!
Maybe my initial question was missleading, sorry for that. Your solution would not include mixed results on the same page with different layouts. I don't want the user to choose what he is searching for. I just want to display the corresponding content templates based on the of post types the query will result in.
E.G. if the search query "lorem" will give result of 1 movie and 1 blog post, I want 2 different layouts on the same results page.
I could think of coding my own search.php, but then I would need to recreate the generatepress content templates that were made with Gutenberg.
To build upon my idea from my second post: something like a generate_get_block_element_template function would do it:
<?php
get_header();
?>
<div>
<?php
if (have_posts()) {
while (have_posts()) {
the_post();
if ('movie' === get_post_type()){
generate_get_block_element_template(5666);
}elseif ('charitiyscrening' === get_post_type()){
generate_get_block_element_template(13802);
}else{
generate_get_block_element_template(11166);
}
}
echo paginate_links();
} else {
echo '<h2>No results matched that search.</h2>';
}
get_search_form();
?>
</div>
<?php
get_footer();
?>
I see. Thank you for clarifying!
You’ll need a snippet like this:
add_filter( 'generate_should_render_content_template', function( $display, $post_id ) {
if(is_search()){
$post_type = get_post_type( get_the_ID() );
if ( $post_id === 395120 ) {
if ( $post_type === 'CPT-1' ) {
$display = true;
} else {
$display = false;
}
}
if ( $post_id === 395121 ) {
if ( $post_type === 'CPT-2' ) {
$display = true;
} else {
$display = false;
}
}
if ( $post_id === 123 ) {
if ( $post_type === 'post' ) {
$display = true;
} else {
$display = false;
}
}
}
return $display;
}, 10, 2 );
Kindly set the display rule location of you Block Element - Content Templates to search results. Then, replace 395120, 395121, 123 with the ID of the elements.
Replace CPT-1 and CPT-2, and post if necessary with the CPT post type slug.
Hope this helps!
Thank you very much!
That's the filter to use for my case.
I managed to get it working. However I needed to modify it. I got rid of the if(is_search()) condition and also changed !== to ===. So if someone can make use of it, here is my code:
add_filter('generate_should_render_content_template', 'ffu_block_templates', 10, 2);
function ffu_block_templates($display, $post_id)
{
$post_type = get_post_type(get_the_ID());
if (13802 === $post_id) {
if ('charityscreening' === $post_type) {
$display = true;
} else {
$display = false;
}
}
if (5666 === $post_id) {
if ('movie' === $post_type) {
$display = true;
} else {
$display = false;
}
}
if (11166 === $post_id) {
if ('post' === $post_type || 'in-front-of-camera' === $post_type || 'behind-camera' === $post_type || 'help' === $post_type || 'donation' === $post_type || 'page' === $post_type) {
$display = true;
} else {
$display = false;
}
}
return $display;
}
I suggest adding the generate_should_render_content_template filter to your documentation.
You’re welcome Aaron! Good catch! Glad you got it to work! Thank you for the recommendation!