This Pro tutorial shows how to modify a Bricks‘ query loop parameters to only show the posts of a CPT that is indirectly related to the current single CPT item when using Meta Box.
Consider this scenario:
Custom Post Types:
- Members
- Orders
- Trainings
Requirement: On a single member page, show all the related posts of training. Note that there is no direct relationship between member CPT and training CPT.
Relationships:
- Members and Orders
- Orders and Trainings
Sample posts:
- Training 1 Connected From Order 2.
- Training 2 Connected From Order 1 and 2.
- Training 3 Connected From Order 1.
- Member 1 Connected To Order 1.
- Member 2 Connected To Order 2.
Objective:
When viewing Member 1, show trainings 2 and 3. This is because Member 1 is connected to Order 1 and this order is connected to Training 2 and Training 3.
Screenshots:
Relationship: Orders and Trainings

Relationship: Members and Orders

We are also going to ensure that the Section in which the indirectly related CPT items are output gets rendered only if there is at least 1 such published CPT item.
Step 1
Create a Bricks template named say “Single Member” of type “Single”.
Edit it with Bricks.
Add a Template setting condition for applying the template to Members CPT.
Add a Section having Post Title and Post Content.
Add another Section having a “Related Training” Heading. We are going to dynamically add “s” at the end of this heading text if there’s more than one published indirectly-related training for the current member.
Add a Container having a Block.
Enable Query Loop on the Block. Select Trainings CPT.
Add a Post Title inside the Block.
At this stage, all the training CPT items will be output.
Step 2
Add the following in child theme‘s functions.php (w/o the opening PHP tag) or a code snippets plugin:
function bl_get_connected_trainings() {
// orders connected from the current member
$connected_orders = MB_Relationships_API::get_connected( [
'id' => 'members-and-orders',
'from' => get_the_ID(),
] );
// if there are no connected orders, abort
if ( empty( $connected_orders ) ) {
return false;
}
// trainings connected from the specified orders
$connected_trainings = MB_Relationships_API::get_connected( [
'id' => 'orders-and-trainings',
'from' => $connected_orders,
] );
foreach ( $connected_trainings as $connected_training ) {
$connected_trainings_ids[] = $connected_training->ID;
}
// return the IDs after removing duplicates
return array_unique( $connected_trainings_ids );
}
// Restrict the trainings based on the value of Meta Box relationship field
add_filter( 'bricks/posts/query_vars', function( $query_vars, $settings, $element_id ) {
// if we are not a singular member page or Meta Box is not active, return the query vars.
if ( ! is_singular( 'member' ) || ! function_exists( 'rwmb_meta' ) ) {
return $query_vars;
}
if ( $element_id === 'oormkn' ) {
$connected_trainings_ids = bl_get_connected_trainings();
if ( $connected_trainings_ids ) {
$query_vars['post__in'] = $connected_trainings_ids;
}
}
return $query_vars;
}, 10, 3 );
function bl_get_connected_trainings_count() {
$connected_trainings_ids = bl_get_connected_trainings();
return $connected_trainings_ids ? count( $connected_trainings_ids ) : false;
}
// Add "s" at the end of a specific heading element's text if there is more than 1 related (by an indirect Meta Box Relationship) post.
add_filter( 'bricks/element/settings', function( $settings, $element ) {
if ( $element->id === 'lhezos' && bl_get_connected_trainings_count() > 1 ) {
$settings['text'] .= 's';
}
return $settings;
}, 10, 3 );
Replace oormkn with the Bricks ID of the query loop element and lhezos with the Bricks ID of heading element.