NO BUG: Can't use global PHP variable in Query editor

I’m using the new Query editor feature from version 1.9.1.

Unsure if this is a bug or if it’s intentional. I’m trying to get the values from a global variable inside the query editor. But no matter what I do, it doesn’t work, not even via custom dynamic tag. I’m trying to achieve something as simple as this code below:

Assuming these are legit post IDs, I have this sample code in a code block somewhere at the top of the template:

global $related_ids;

$related_ids = [123,345,678];

Trying to get the reference to the global variable inside the query editor:

global $related_ids;

return [
  'post_type' => 'post',
  'posts_per_page' => 3,
  'post__in' => $related_ids,
];

It doesn’t work as it is not getting the global variable. I’ve tested the output in a code block and there are no issues with it. Manually setting the array of IDs to ‘post__in’ in the Query editor works.

I need this global variable reference for backward compatibility with years of older posts that are manually passing related post IDs through a shortcode instead of via a custom field. Getting the posts IDs from the shortcode and setting it to a global variable isn’t a problem. I’m just stuck at the Query editor part.

My alternative is to just manually create the query loop and HTML in a code block, but I’d rather this be the last resort.

2 Likes

I have exactly this problem too.
In addition, I cannot use an ACF function either, like in this example:

$cpt_id = {echo:get_field('choose-cpt-add-prod-infos')};
return [
  'post_type' => 'add-prod-info',
  'posts_per_page' => -1,
  'p' => $cpt_id
];

I hope someone knows what to do.

Cheers André

Hi @teoeugene

Since 1.9.1, Bricks optimized the Bricks query which will only execute once before actually rendering the page.

Understand you are using the code element in a page and purposely locate it before the query (Structure panel)
Unfortunately, the Bricks query will be executed far before that, hence your code inside code element will not take any effect.

Notes: Code element’s code will only be executed when rendering on the page.

Visual explanation:
Query execution in previous versions based on your scenario :

  1. Run query for CSS (global $related_ids not set)
  2. Render elements on a page
  3. Render code element, execute code. (global $related_ids = [123,345,678] )
  4. Render query loop element, Run query. (global $related_ids = [123,345,678] )

New query execution based on your scenario:

  1. Run query for CSS, save result in history (global $related_ids not set)
  2. Render elements on a page
  3. Render code element, execute code. (global $related_ids = [123,345,678] )
  4. Render query loop element, reuse the result in step (1) without execute the query again

To solve your issue:
You should place them in a child them by wrapping them in a hook like “wp” to ensure you set the global $related_ids in the beginning. Don’t use code element.

add_action( 'wp', function(){
  global $related_ids;
  $related_ids = [123,345,678];
 });

By doing this, Bricks query will be able to retrieve the global $related_ids in Query editor.

Hope this explains it :slight_smile:

Alternatively, you could use this PHP hook to disable this Bricks optimization, which will force Bricks query multiple times like the old way.

// Place this in child theme, NOT code element
add_filter( 'bricks/query/force_run', '__return_true' );

Regards,
Jenn

1 Like

Thanks @itchycode .

The Code element is an example to test a global variable. The actual global variable comes from a shortcode in the post. Based on your visual explaination, I assume that the action method will not work either because the shortcode is rendered and executed after the query’s history anyway. I briefly tested the method you suggested to confirm that as well. I guess I’m sticking with my backup custom query and HTML loop solution.

Do you have any suggestions with my scenario in mind using Bricks’ Query editor, other than to force_run the query? I’d like to understand how far I can go with the Query editor.

Hi @teoeugene ,

I am not able to visualize the whole picture of your scenario, the shortcode will return the Ids in array?
If so, can you use it in Query editor?

Like:

$related_ids = do_shortcode( '[that_shortcode]' );

return [
  'post_type' => 'post',
  'posts_per_page' => 3,
  'post__in' => $related_ids,
];

Otherwise, you might need to send us temp admin login via help@bricksbuilder.io and briefly record a short video to explain your scenario.

The worst case is to use the force_run filter to force rerun query for that specific query loop only.

Regards,
Jenn

1 Like

The shortcode is inserted at the end of the post’s content and each post has its own different set of related IDs (see example screenshot). In the old layout, the related posts will show at the end of the post content. This is no longer the case as there are other elements in between.

For backward compatibility with an updated layout, the idea was to convert the shortcode callback to assign these IDs to a global variable instead of returning a HTML output, then use that same global variable in the Query editor.

Hi @teoeugene ,

I personally don’t think this will work if you don’t move the shortcode out and store those IDs in a custom field or relationship field.

Bricks query will not be able to read the Gutenberg content before rendering it.

Regards,
Jenn

Yeah, I figured as much. It’s not that I don’t want them in custom field, it’s more that I can’t (it’s hundreds of old posts). Anyhow, I’ve a backup implementation that works. Thanks for your replies in this thread.

1 Like

Thank you itchycode.
bricks_force_run’ does the trick.

This works now for me:

return [
  'post_type' => 'add-prod-info',
  'posts_per_page' => -1,
  'bricks_force_run' => true,
  'p' => get_field('choose-cpt-add-prod-infos')[0]
];
2 Likes