Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query block with shortcode breaks get_the_ID or get_post #43053

Open
Bellian opened this issue Aug 7, 2022 · 37 comments
Open

Query block with shortcode breaks get_the_ID or get_post #43053

Bellian opened this issue Aug 7, 2022 · 37 comments
Labels
[Block] Query Loop Affects the Query Loop Block [Block] Shortcode Affects the Shortcode Block [Type] Help Request Help with setup, implementation, or "How do I?" questions.

Comments

@Bellian
Copy link

Bellian commented Aug 7, 2022

Description

I am curently using the block editor to create a website.
Since I am using custom post types and custom taxonomys and custom meta data, there is currently no way to to display these.

So i included a shortcode to render those relevant informations.
this worked fine for single posts, but as soon as I used this in archives within the content loop, get_the_ID or get_post only return data from the first post in the query. In this case i may find a workaround by just counting how many times this hortcode is called and accesing the id by the $posts array, but still, this would be awesome if this could be fixed.

Step-by-step reproduction instructions

  1. Create shortcode:
add_shortcode('archive_code', function(){ return get_the_ID(); });
  1. Use inside a archive loop

Screenshots, screen recording, code snippet

image

The "Featured Image" is added by the block editor. There you see the two images.
The text on the side shows the bug. They both have the same ID (marked in red).

Environment info

  • Wordpress: 6.0.1
  • Gutenberg: whatever comes shipped with it.

Please confirm that you have searched existing issues in the repo.

Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

Yes

@Bellian
Copy link
Author

Bellian commented Aug 8, 2022

I just found:
Calling do_shortcode within the render_block_core_shortcode method solves this problem.

function render_block_core_shortcode( $attributes, $content, $block ) {
	$result = wpautop( $content );
	return do_shortcode($result);
}

So are shortcodes executed at a later point then?
This can be a bit unintuative.

Are there other ways to do what i am trying to do?

@carolinan carolinan added [Type] Help Request Help with setup, implementation, or "How do I?" questions. [Block] Query Loop Affects the Query Loop Block [Block] Shortcode Affects the Shortcode Block labels Aug 8, 2022
@carlomanf
Copy link

This looks like a duplicate of #35676, where the solution was given at #35676 (comment)

@Bellian
Copy link
Author

Bellian commented Aug 8, 2022

Well, kind of.
It only solves one manifestation of the problems.
The shortcode block is still lacking the ability to access current the posti id, since it is apparently evaluated at a later point.

Since a lot of plugins and users use shortcodes still, it might be beneficial to be able to use it in this context.

The fix is also straight forward and apparently works or is there a drawback to it I don't see.
It can even be made more easy using:

function render_block_core_shortcode( $attributes, $content, $block ) {
	return do_shortcode($content );
}

This will also prevent adding blank lines arrount the shortcode.

@carlomanf
Copy link

I see what you are saying and I have previously proposed the same change, albeit to solve a different problem. I still think the issue is a duplicate, just that you have explained it better than the other issue.

@Bellian
Copy link
Author

Bellian commented Aug 8, 2022

Shure thing. Good call.
If you dont mid, I took the freedom to post a working workarround that solves this problem right now, also mentioning potential problems comming from that. #35676 (comment)

It was just trubling to me to close this issue in favor of an already closed one, that does not solve the underlying problem.

@gabbsmo
Copy link

gabbsmo commented Oct 30, 2022

Just want to point out that this also applies to shortcodes in block content such as paragraphs as well, not just the shortcode block.

While I understand that blocks are the future, shortcodes are currently the only way to inline dynamic content.

Example:
[webinar_start_date] at [webinar_start_time]-[webinar_end_time]

1 December 2022 at 9 am-10 am

@kaffeeringe
Copy link

I need this solution too.

@kaffeeringe
Copy link

kaffeeringe commented Dec 31, 2022

function render_block_core_shortcode( $attributes, $content, $block ) {
	return do_shortcode($content );
}

This doesn't work for me. Problem remains the same. :-(

@bobbingwide
Copy link
Contributor

A simpler solution to the logic that overrides the dynamic rendering logic for the shortcode block is to implement a hook for the filter that's run at the end of each block.

/**
 * Filters the rendered shortcode block.
 *
 * @param $content
 * @param $parsed_block
 * @param $block
 * @return mixed|string
 */
function fizzie_render_block_core_shortcode( $content, $parsed_block, $block ) {
    $content = do_shortcode( $content );
    return $content;
}
add_filter( 'render_block_core/shortcode', 'fizzie_render_block_core_shortcode', 10, 3, );
add_filter( 'render_block_core/paragraph', 'fizzie_render_block_core_shortcode', 10, 3, );

This is how I've chosen to implement the fix for my Fizzie theme.
See bobbingwide/fizzie#28 (comment) for more details.

@Odinnh
Copy link

Odinnh commented Apr 11, 2023

A simpler solution to the logic that overrides the dynamic rendering logic for the shortcode block is to implement a hook for the filter that's run at the end of each block.

/**
 * Filters the rendered shortcode block.
 *
 * @param $content
 * @param $parsed_block
 * @param $block
 * @return mixed|string
 */
function fizzie_render_block_core_shortcode( $content, $parsed_block, $block ) {
    $content = do_shortcode( $content );
    return $content;
}
add_filter( 'render_block_core/shortcode', 'fizzie_render_block_core_shortcode', 10, 3, );
add_filter( 'render_block_core/paragraph', 'fizzie_render_block_core_shortcode', 10, 3, );

This is how I've chosen to implement the fix for my Fizzie theme. See bobbingwide/fizzie#28 (comment) for more details.

thanks, i've had the same problem and this was the only sollution that came close.

though for some reason this creates "phantom" paragraphs around the result block a.e.
<p></p> <figure....> <p></p>
i can remove these paragraphs with JS but i'd hope there is a better alternative

@saemideluxe
Copy link

Hi there

The proposed solutions do not work for me. Either replacing the content of render_block_core_shortcode directly or adding the filter. Could this be related to the newest Wordpress update 6.2.1 or 6.2.2?

However, I had the do_shortcode inside a render_block filter for a long time and just recently encountered the issue. Any advice? Our site is completely broken ATM.

@nandoj
Copy link

nandoj commented May 24, 2023

Hi there

The proposed solutions do not work for me. Either replacing the content of render_block_core_shortcode directly or adding the filter. Could this be related to the newest Wordpress update 6.2.1 or 6.2.2?

However, I had the do_shortcode inside a render_block filter for a long time and just recently encountered the issue. Any advice? Our site is completely broken ATM.

This was working fine (I think) for a while even in 6.2.2, but today I noticed its not working again. Last time it broke (first solution) was updating from 6.2.1 but now I haven't done anything and still it fails to work. Will try to do a quick research and reply back.

@bobbingwide does this still work for you? I can't figure out why it stopped working all of the sudden.

@saemideluxe
Copy link

In case this helps anyone: I tried to downgrade, but found the problem still existed with 6.1.3. However, 6.1.2 worked. I am looking at the diff between the two. There are a few intersting things, but I am short on time right now. When using linux the diff can easily be viewed with:

git clone git://develop.git.wordpress.org/ && cd develop.git.wordpress.org/ && git diff 6.1.2 6.1.3

@PH4NTOMiki
Copy link

@saemideluxe it looks like it's in src/wp-includes/blocks/template-part.php
the order of some lines were change, and I'm pretty sure that's the reason it's not working properly.

@saemideluxe
Copy link

Right, I read it too now. But I am completely lost about why exactly this change would cause things to stop working X-D

@PH4NTOMiki
Copy link

I think it's because do_shortcode is now after do_blocks

@spacedragn
Copy link

fwiw @Bellian‘s theme-level workaround is still working for me.

@PH4NTOMiki
Copy link

For me, it was working in 6.2 and it stopped in 6.2.1 (and 6.2.2) so I had to downgrade

@PH4NTOMiki
Copy link

Theme level workaround

@Bellian
Copy link
Author

Bellian commented Jul 30, 2023

It also worked for me untill 6.2.
After that somehow all the posts had the same postid.
While debuging I noticed that apparently during template parsing the shortcode got evaluated once and somehow cached?

My workarround was then to simply replace the shortcode with another shortcode and let it evaluate during the loop..

add_shortcode('my_shortcode', 'render_shortcode');
add_shortcode('my_shortcode_render', 'render_shortcode_real');

function render_shortcode_real($atts)
{
    // render your stuff!
}
function render_shortcode($atts)
{
    return '[my_shortcode_render]';
}

@lgladdy
Copy link

lgladdy commented Aug 1, 2023

I wrote a quick workaround for ACF here by replacing the default core/shortcode block renderer with one with adds the Post ID to ACF shortcodes: https://gist.github.com/lgladdy/7c83332eba10e6a5338fd298ed855f16

The main issue is that the shortcode block isn't responsible for rendering it's own shortcodes, so the context that's provided to the renderer which would make get_the_ID() work is no longer available at the shortcode's actual render time.

There's probably a couple of ways this could be resolved, or at least optimised:

  1. The shortcode block renderer should be responsible for running do_shortcode by itself. This would make the context available correctly to the shortcodes.
    2) The default block renderer should apply a filter, to make manually supporting this easier for plugins (if the Gutenberg team don't won't to move the rendering point) I realised reading some of the other examples, you can already do this using the render_block_core/shortcode filter.

@jaroszeo
Copy link

jaroszeo commented Oct 6, 2023

@lgladdy works great for me, but Im afraid its not the fastest way on server side. I hope soon wordpress will fix this issue.

@etzel42
Copy link

etzel42 commented Nov 20, 2023

This is still very much an issue.. I had been using a hook to call do_shortocde() as @bobbingwide had suggested and this was working fine, but now, perhaps since 6.4, its no longer working.

Why is this not a top priority for word press to get this fixed once and for all?

Any new workarounds? This has completely killed my site.

@saemideluxe
Copy link

saemideluxe commented Nov 21, 2023 via email

@SpinnerWebs
Copy link

SpinnerWebs commented Dec 29, 2023

It also worked for me untill 6.2. After that somehow all the posts had the same postid. While debuging I noticed that apparently during template parsing the shortcode got evaluated once and somehow cached?

My workarround was then to simply replace the shortcode with another shortcode and let it evaluate during the loop..

add_shortcode('my_shortcode', 'render_shortcode');
add_shortcode('my_shortcode_render', 'render_shortcode_real');

function render_shortcode_real($atts)
{
    // render your stuff!
}
function render_shortcode($atts)
{
    return '[my_shortcode_render]';
}

@Bellian Tried this on 6.4.2 but no joy (also tried with do_shortcode()). Does it still work for you?

@Mr2P
Copy link

Mr2P commented Jan 26, 2024

Anyone who still gets stuck with this issue can use my plugin Meta Field Block to solve it. My plugin has been referred to as a solution to a similar issue here. Since version 1.2.3, it has native support for running shortcode. You just set the field type to dynamic and enter the shortcode in the field name, and the shortcode will be displayed correctly. This plugin is also better than the core/shortcode block by adding the ability to show the preview of shortcodes on the backend.

@kaffeeringe
Copy link

kaffeeringe commented Jan 26, 2024 via email

@SpinnerWebs
Copy link

Anyone who still gets stuck with this issue can use my plugin Meta Field Block to solve it. My plugin has been referred to as a solution to a similar issue here. Since version 1.2.3, it has native support for running shortcode. You just set the field type to dynamic and enter the shortcode in the field name, and the shortcode will be displayed correctly. This plugin is also better than the core/shortcode block by adding the ability to show the preview of shortcodes on the backend.

This is great. Thanks @Mr2P!

@etzel42
Copy link

etzel42 commented Jan 26, 2024 via email

@Mr2P
Copy link

Mr2P commented Jan 27, 2024

@etzel42 You could remove the wrapped HTML like this:

add_filter( 'render_block', function ( $block_content, $block ) {
  if ( 'mfb/meta-field-block' === $block['blockName'] ) {
    
    // Define your regex pattern.
    $pattern = '/<div class=\'value\'>(.*?)<\/div>/s';
    
    // Perform the regex search.
    preg_match($pattern, $block_content, $matches);

    if ( $matches ) {
      return $matches[1];
    }    
  }

  return $block_content;
}, 10, 2);

I have not tested it myself, but I think it should work.

@yankiara
Copy link

Anyone who still gets stuck with this issue can use my plugin Meta Field Block to solve it. My plugin has been referred to as a solution to a similar issue here. Since version 1.2.3, it has native support for running shortcode. You just set the field type to dynamic and enter the shortcode in the field name, and the shortcode will be displayed correctly. This plugin is also better than the core/shortcode block by adding the ability to show the preview of shortcodes on the backend.

@Mr2P: Man, this is awesome, you just saved me from total madness. Rebuilding a site with a lot of dynamic stuff and with only native WP blocks, I have to fully rely on shortcodes (back to old school WP), and I'm so shocked that we can't access post ID inside the loop!!! Thanks a zillion!

@Mr2P
Copy link

Mr2P commented Apr 15, 2024

@yankiara you are welcome. I'm glad you found it helpful.

@yankiara
Copy link

yankiara commented Apr 17, 2024

@Mr2P I can't get it working with wrapped content shortcodes:

MFB dynamic [shortcode]
Content....
MFB dynamic [/shortcode]

Am I missing something or is it not supported?
Would you know a workaround for this?
(I use this a lot for dynamic visibility conditions.)

@Mr2P
Copy link

Mr2P commented Apr 18, 2024

@yankiara, this works with all types of shortcodes. Could you please provide me with your code? I will investigate your issue. Also, could you post it on the plugin support page? This thread is not about this plugin.

@frzsombor
Copy link

Solution for WP Shortcodes in Query Loop Post Templates

The problem

Before rendering a page, WordPress first generates the output for all blocks without actually printing them. When using a Query Loop, during each "loop cycle" WordPress generates the block code for each loop item using its render_block() function. Here, we still have access to the "current" post, however, the issue is that WordPress does not process shortcodes in its render function. Instead, shortcodes are only processed when the full page content is outputted (composed of the previously rendered blocks). By that point, the shortcodes will no longer have access to their corresponding post but instead will refer to the current post, which is the rendered page itself.

The solution

I was looking for a solution that doesn't require "hacking" the core of WordPress. It needed to be lightweight, universal, easy to use, and configurable, relying solely on native approaches. Additionally, it had to ensure that everything works as originally intended where this solution isn't needed.

For all details, ready to use code and usage guide please check this gist that I've dedicated to this:
🔧✨ https://gist.github.com/frzsombor/c53446050ee0bb5017e29b9afb039309


image

@robizzt
Copy link

robizzt commented Dec 3, 2024

A similar bug is happening when using a Shortcode block while building a template in the Site Editor.

When I use the Shortcode block while editing a single post (as in "post-content"), it works correctly.
But when used in the Site Editor while editing template, the Shortcode block gets wpautop() and breaks the layout.

I'm working on WP version 6.7.1.

And this is the solution I am using for now:

add_filter('render_block_core/shortcode', function($content, $parsed_block, $block) {
	return $parsed_block['innerHTML'];
}, 10, 3);

@robizzt
Copy link

robizzt commented Dec 3, 2024

Also, funny thing is when using Shortcode block in Post editor, $parsed_block['innerHTML'] is:
[custom-test test1="test1" test2=test2 test3]

And when using in Site Editor while editing template, $parsed_block['innerHTML'] is:
<div class="testing">Test</div>
So that's probably why this code gets wpautop().

But in both ways, I get HTML displayed as expected with the solution above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Query Loop Affects the Query Loop Block [Block] Shortcode Affects the Shortcode Block [Type] Help Request Help with setup, implementation, or "How do I?" questions.
Projects
None yet
Development

No branches or pull requests