How to Inject a Different Type of Post in Bricks Query Loop

Updated on 26 Aug 2024

A user asks:

Hello, I’d like to inject a CPT post card inside of a Bricks query loop of a different CPT and display every 10 posts. The specific use is to display a Classified Ads CPT card within News CPT search results that is filtered by Grid WP.

bricks/query/result filter introduced in Bricks 1.8 enables us to modify the query results before Bricks renders the output.

This Pro tutorial shows how we can use this filter to inject a specific post (can be of any post type) in between posts as every nth item in Bricks query loop output.

Single Tutorial Purchase Option

Lifetime access to this single tutorial can be purchased for $39 here.

Step 1

Edit a Page with Bricks and set up a query loop on a Block element.

The initial structure would look like this:

In this example we shall insert a specific product (by its ID) in between regular posts after every 2nd post.

Therefore there is no need to specify the post type since post is the default in Query settings.

Add a Heading element inside the Block and set its text to:

{post_title:link}

Change its label to say, “Post Heading”.

Apply a Dynamic data condition to make this element be rendered only if the current post type is post.

Duplicate the “Post Heading” as “Product Heading”.

Change the value in the condition from post to product, assuming WooCommerce is active in your install or there is a CPT with that name – if not, change it to post type of your choice.

Practically speaking, you probably want to have cards instead of just linked titles.

Therefore, after implementing the next step and ensuring that everything is working as it should, you might want to come back and replace the above two headings with two Blocks or Divs that are parent containers of your card elements and apply the same conditions on the parent elements.

Step 2

Add the following in child theme‘s functions.php or a code snippets plugin:

/**
 * Modify the query result for a specific Bricks element.
 *
 * This function intercepts the query result for the Bricks element with ID 'xnbxmp'.
 * It adds a specific post (ID 209) after every 2nd post in the result set.
 *
 * @param WP_Query $result    The original query result.
 * @param object   $query_obj The query object containing element information.
 *
 * @return WP_Query Modified query result.
 */
add_filter( 'bricks/query/result', function( WP_Query $result, object $query_obj ) : WP_Query {
    // Return early if the element ID is not "xnbxmp"
    if ( $query_obj->element_id !== 'xnbxmp' ) {
        return $result;
    }

    // Proceed only if the query has posts
    if ( $result->have_posts() ) {
        // Extract an array of post IDs from the result object
        $post_ids = wp_list_pluck( $result->posts, 'ID' );
        
        // Define the post ID to be inserted and the interval
        $insert_post_id = 209;
        $insert_interval = 2;

        // Calculate the number of posts and the starting position for insertion
        $total_posts = count( $post_ids );
        $start_position = $total_posts - ( $total_posts % $insert_interval );

        // Insert the specified post ID at calculated intervals
        for ( $position = $start_position; $position > 0; $position -= $insert_interval ) {
            array_splice( $post_ids, $position, 0, $insert_post_id );
        }
        
        // Convert the array of post IDs back to an array of post objects
        $posts = array_map( function( int $post_id ) : WP_Post {
            return get_post( $post_id );
        }, $post_ids );
    
        // Update the posts property of the result object
        $result->posts = $posts;
    }

    return $result;
}, 10, 2 );

Replace xnbxmp with the Bricks ID of the element on which query loop has been applied.

Replace 209 with the ID of your post (can be of any post type) that you wish to insert.

Change 2 in $insert_interval = 2; as needed.

Step 3

Whitelist the get_post_type function.

Ex.:

<?php 

add_filter( 'bricks/code/echo_function_names', function() {
  return [
    'get_post_type'
  ];
} );

You should also add other functions (native or custom) being used in your Bricks instance besides get_post_type. This can be checked at Bricks → Settings → Custom code by clicking the Code review button.

More info on whitelisting can be found here.

Reference

https://stackoverflow.com/a/73576397/778809