Accessing component properties in custom query (PHP)

Bricks Component: Querying Posts by ID - Solution

What I Was Trying to Do

I wanted to create a reusable Bricks component with a field where users could enter comma-separated post IDs (e.g., “123,456,789”), and have a query loop display those specific posts.

The Problem I Faced

Bricks doesn’t provide a straightforward way to query posts by their IDs through the component UI. The main issues were:

  1. Component fields only appear if they’re bound to something - You can’t just create a field and access it directly in a query

  2. No “Post IDs” or “Include by ID” field exists in the standard Bricks query interface

  3. Can’t use PHP Query Editor - Enabling it removes the field binding, so users can’t input the IDs

  4. Post IDs aren’t meta fields - They’re in the main wp_posts table, not wp_postmeta, so a standard meta query won’t work

The Workaround

The solution was to use a “fake” meta query as a bridge to access the component field data, then intercept and modify the query using a filter:

Component Setup:

  1. Create a text field labeled “Article IDs” in the component

  2. In the query loop’s Meta Query settings:

    • Meta key: _component_article_ids (this is just a unique identifier, doesn’t need to exist in DB)

    • Meta value: Bind to the “Article IDs” field

    • Compare: IN

    • Type: NUMERIC

The Filter Code:

<?php
/**
 * Bricks Component: Article IDs Query Filter
 * 
 * This filter allows Bricks components to query posts by their IDs using a component field.
 * 
 * THE PROBLEM:
 * - Bricks components can't directly use post__in queries through the UI
 * - Component fields need to be "bound" to query settings to appear in the editor
 * - We bind the field to a meta query, but post IDs aren't meta fields - they're in the main posts table
 * 
 * THE SOLUTION:
 * - Create a component field called "Article IDs" where users enter comma-separated post IDs
 * - Bind that field to a meta query with key "_component_article_ids" (this makes the field visible)
 * - This filter intercepts the query, extracts the post IDs from the component field
 * - Removes the fake meta query and replaces it with a proper post__in query
 * 
 * COMPONENT SETUP:
 * 1. Create a text field labeled "Article IDs"
 * 2. In the query loop's Meta Query settings:
 *    - Meta key: _component_article_ids
 *    - Meta value: Bind to "Article IDs" field
 *    - Compare: IN
 *    - Type: NUMERIC
 * 
 * The meta key "_component_article_ids" is just a unique identifier - it doesn't need to exist
 * in the database. It's only used so this filter knows which query to modify.
 */

add_filter('bricks/posts/query_vars', function($query_vars, $settings, $element_id) {
    
    // Check if we have our meta query
    if (isset($query_vars['meta_query'])) {
        foreach ($query_vars['meta_query'] as $key => $meta) {
            // Look for our specific component meta key
            if (isset($meta['key']) && $meta['key'] === '_component_article_ids') {
                
                // Get the ID from the original settings (not query_vars)
                // Bricks strips the internal 'id' field when converting to query_vars
                if (isset($settings['query']['meta_query'])) {
                    foreach ($settings['query']['meta_query'] as $settings_meta) {
                        if (isset($settings_meta['key']) && $settings_meta['key'] === '_component_article_ids' && isset($settings_meta['id'])) {
                            $meta_id = $settings_meta['id'];
                            
                            // Get the value using the meta ID
                            // Bricks stores component field values with this key pattern
                            $settings_key = "meta_query|{$meta_id}|value";
                            $article_ids_value = $settings[$settings_key] ?? '';
                            
                            if (!empty($article_ids_value)) {
                                // Convert comma-separated string to array of integers
                                $ids = array_map('intval', array_filter(explode(',', $article_ids_value)));
                                
                                if (!empty($ids)) {
                                    // Remove meta query and use post__in instead
                                    unset($query_vars['meta_query']);
                                    $query_vars['post__in'] = $ids;
                                    $query_vars['orderby'] = 'post__in';
                                }
                            }
                            break;
                        }
                    }
                }
                
                break;
            }
        }
    }
    
    return $query_vars;
}, 10, 3);

How It Works

  1. The component field gets bound to the meta query, making it visible to users

  2. When users enter post IDs (e.g., “18627,18628”), Bricks stores this value in the settings

  3. The filter intercepts the query before it runs

  4. It extracts the post IDs from the component field value

  5. Removes the meta query (which wouldn’t work anyway for post IDs)

  6. Replaces it with post__in to properly query posts by their IDs

Key Discovery

Bricks stores component field values in a hidden format: meta_query|{internal_id}|value. The internal ID exists in $settings['query']['meta_query'] but gets stripped when converted to $query_vars['meta_query']. You have to access the original settings to retrieve it.

This workaround is necessary because Bricks doesn’t document how to programmatically access component field data or provide a native way to query posts by ID within components.

So…. this fixes the current issue and hopefully will be a guide with fixing other issues when accessing component data to create more flexible blocks.