Closed julian-stark closed 3 years ago
Hey @julian-stark 👋 - You can consume the postId
in a block by declaring in that block's block.json
it uses this context (example here) and then consume it in client and server side.
thank you @ntsekouras seems not too easy with my limited gutenberg dev experience 😃 would I "extend" the current query block?
Can you describe more your use case? I thought you have created a block that would like to have postId
inside Query Loop
..
I would like to use the default query loop block. For each post displayed by the loop I would like to output a custom field (ACF) which shows a date in the future (besides title, and content).
To accomplish that easily I would use a shortcode (I fear you don't like to read this 😨 ). In the shortcode I need to get the current postID of the query loop to use it in the get_field() function.
For each post displayed by the loop I would like to output a custom field (ACF) which shows a date in the future (besides title, and content).
So is this date a custom block of yours? If yes the above comment should do.
My hope was that there is something like the get_the_ID() function for the query block that allows me to get the current query block post_ID in a php function used for a shortcode.
but thank you!
I'm not sure if I was helpful here 😄 . Do you need any clarifications? If not, should we close this issue? 🤔
Yes you were, thank you. The thing is only that i need to start building something the gutenberg way and not the classic shortcode way :)
FWIW. Same problem.
I expected get_the_ID() to work within a custom function inside the Query Loop Block and it doesn't seem to. I was trying for the same reason, I needed it to get a custom field via get_post_meta() (actually a set by ACF), from inside the query loop and cant' seem to. Really wish there were more developer documentation on the Query Loop block like how to use it for CPTs and Custom Fields.
@jb510 Perhaps this helps, because I found this thread looking for a solution myself just now.
If you use [acf_register_block_type($settings)]
(https://www.advancedcustomfields.com/resources/acf_register_block_type/) to create a block with the ACF Block functionality (which I did), and you want to access the 'post_id' of the current post inside the query loop - instead of the main post_id the post/page, you need to add 'usesContext' => [ 'postId' ]
to the $settings.
Then the $post_id in render_callback
or render_template
in PHP that ACF provides will be the id of the post in the loop.
What gave me a tip is that in $settings you can pass any parameter that Gutenbergs Javascript registerBlockType()
accepts, together with above answer of @ntsekouras
Thank you. But I trying to do the opposite, access the post_id of the post object inside the loop created by the query loop block. Not the post_id outside it.
I suspect I could do it using the server side code ntsekouras linked above, but... that's more code than I want to deal with when I can just use a traditional page template here to get what I wanted. Someday perhaps I'll tackle that, but not today.
EDIT: Been thinking about this. @morksinaaban I might need to give this is a try. I misunderstood the usesContext flag, maybe that'll work for my needs.
👋 We'll be making changes in our WP5.9 compatibility fix release which solves this problem in ACF, as this is also an issue in the full site editor.
@lgladdy, now that 5.9 is out can you shed any more light on how it will address this situation? I think it's going to be really common to want to use an [acf field="..."] shortcode for posts/CPTs that are retrieved via some arbitrary block's custom query loop. Using the solution described by @morksinaanab seems to be overly complicated for this common scenario, especially given that you may not be the author of the particular block type.
Yes you were, thank you. The thing is only that i need to start building something the gutenberg way and not the classic shortcode way :)
@julian-stark, how did you finally solve this problem?
If you use
[acf_register_block_type($settings)]
(https://www.advancedcustomfields.com/resources/acf_register_block_type/) to create a block with the ACF Block functionality (which I did), and you want to access the 'post_id' of the current post inside the query loop - instead of the main post_id the post/page, you need to add'usesContext' => [ 'postId' ]
to the $settings.Then the $post_id in
render_callback
orrender_template
in PHP that ACF provides will be the id of the post in the loop.
@morksinaanab, do you have any suggestions for how you would achieve this within a block you did not write yourself and don't want to modify, such as that provided by a 3rd party plugin?
I’m experiencing the same pain points as OP here. In an ideal world, we could natively access any metadata within the Query Loop > Post Template as we do in custom PHP queries with get_post_meta()
. Is this in the roadmap? I’ve been sifting through open tickets and can’t discern if this is a short term priority.
Right now, I’m unable to hack a solution together using custom shortcodes as OP described, which means abandoning the Query Loop/Post Template block altogether and relying on old methods again.
Why is this ticked closed?
There currently is no easy way to just render any shortcode and access post data? Why not?
Writing a shortcode is much easier than creating a new block...
Why is the query loop block query soo different to the wp_query loop?
This whole situation became a huge time sink! I never found a good solution for using a shortcode... but if anyone's trying to just output post meta inside a Query Loop block, this smart plugin from @Mr2P saved me a TON of time: https://wordpress.org/plugins/display-a-meta-field-as-block/
Note: It works with any meta, not just ACF. Also, It has some non-critical issues (hard to find the block once you've placed it & it doesn't show the post meta value while you're editing) (I actaully added custom css just to highlight it in the editor). But by and large, it's incredibly clever & helpful.
The problem is already adressed here https://github.com/WordPress/gutenberg/issues/37754#issuecomment-1013559781 and a fix already proposed but the issue is apparently pending. So I have a relatively easy fix for everyone who does not want to create these custom blocks in order to get shortcodes working again as expected.
Just copy wp-includes/blocks/shortcode.php
and the wp-includes/blocks/shortcode
folder to your theme.
Change your shortcode.php
:
<?php
/**
* Server-side rendering of the `core/shortcode` block.
*
* @package WordPress
*/
/**
* Performs do_shortcode() on the shortcode block content.
*
* @param array $attributes The block attributes.
* @param string $content The block content.
*
* @return string Returns the block content.
*/
function sp_render_block_core_shortcode( $attributes, $content, $block ) {
return do_shortcode($content);
}
/**
* Registers the `core/shortcode` block on server.
*/
function sp_register_block_core_shortcode() {
unregister_block_type( 'core/shortcode' );
register_block_type_from_metadata(
__DIR__ . '/shortcode',
array(
'render_callback' => 'sp_render_block_core_shortcode',
)
);
}
add_action( 'init', 'sp_register_block_core_shortcode' );
Include the shortcode.php
and it should be fixed.
Potential problem at the moment could be, that shortcodes generated in there as content might be parsed again.
This is still an issue with WP 6.1.1.
I agree that this needs to be re-opened. It's crazy that we have no way to get the post ID in a query block. As mentioned earlier, a very basic use case would be if we need to add custom fields to posts or a cpt. For instance, let's say we want to add "itunes podcast URL" to any posts tagged "podcast." If we use the Query Block to pull in those posts, we have no way to visually display the custom field - let's say we'd want to add a itunes icon that had the link. We can't do that. This is just one of many examples I could come up with.
1 year later, I’m still writing shortcodes to output metadata/ACF in Post Templates and using Bellian’s patch to pass post IDs. It appears decision makers expect us to use React and scaffold custom blocks to output this data, despite years of using one line of PHP to achieve the same result.
It appears decision makers expect us to use React and scaffold custom blocks to output this data, despite years of using one line of PHP to achieve the same result.
You don't need to use React, you can use vanilla JS and PHP.
I agree that this needs to be re-opened.
@Mr2P saved me a TON of time: https://wordpress.org/plugins/display-a-meta-field-as-block/
This helped me.
Background: I also run into the same issue by not getting the correct id using shortcode in gutenberg loop block. At first I got the shortcode running in the query loop block and use correct ID by using similar code like @Bellian But it still failed in the query loop block that I was using in full site editor (2023 theme) to loop items in custom taxonomy term. I somehow got ony the ID of the first item and every item afterwards had the same id.
Thank you @Mr2P! May the plugin live long and prosper
Thank you @brandonjp and @kaiakonsap for mentioning my plugin MFB here. I’m glad you guys like it. I have a big plan for it, so I will support and maintain it constantly.
@Mr2P Would I be able to use your plugin if I'm not using ACF. I just have a shortcode that I want to pull a custom field from (using a Yoast custom field) and I need to be able to get the post ID automatically within the loop rather than inputing it. Sorry, not explaining well, but maybe this will help...
I want to show a meta field from a post (outside of the loop) when using the Query Block.
So let's say I have a Query Block like this:
<!-- wp:post-template {"layout":{"type":"grid","columnCount":"1"}} --><!-- wp:columns {"align":"wide","style":{"spacing":{"margin":{"top":"0","bottom":"0"}}},"className":"equal-height-columns"} --><div class="wp-block-columns alignwide equal-height-columns" style="margin-top:0;margin-bottom:0"><!-- wp:column {"width":"70%"} --><div class="wp-block-column" style="flex-basis:70%"><!-- wp:post-featured-image {"isLink":true,"aspectRatio":"4/3"} /--></div><!-- /wp:column --><!-- wp:column {"width":"30%"} --><div class="wp-block-column" style="flex-basis:30%"><!-- wp:group {"className":"is-style-default stretch-content-to-match-height","layout":{"type":"constrained"}} --><div class="wp-block-group is-style-default stretch-content-to-match-height"><!-- wp:group {"layout":{"type":"constrained"}} --><div class="wp-block-group"><!-- wp:post-terms {"term":"category"} /--><!-- wp:post-title {"isLink":true,"style":{"spacing":{"margin":{"top":"var:preset|spacing|10"}}}} /--><!-- wp:post-author {"byline":"By","style":{"spacing":{"margin":{"top":"var:preset|spacing|20"}}}} /--><!-- wp:shortcode -->[yoast-primary-category]<!-- /wp:shortcode --></div><!-- /wp:group --><!-- wp:post-excerpt {"moreText":"Read Article","className":"last-block"} /--></div><!-- /wp:group --></div><!-- /wp:column --></div><!-- /wp:columns --><!-- /wp:post-template -->
Let's say I have multiple similar blocks on the same page with different offset values etc. so I can control the style a bit more on the page.
Then, my shortcode looks like:
// GET PRIMARY (OR FIRST) CATEGORY
function get_yoast_primary_cat() {
$category = get_the_category();
$useCatLink = true;
// If post has a category assigned.
if ($category){
$category_display = '';
$category_link = '';
if ( class_exists('WPSEO_Primary_Term') )
{
// Show the post's 'Primary' category, if this Yoast feature is available, & one is set
$wpseo_primary_term = new WPSEO_Primary_Term( 'category', get_the_id() );
$wpseo_primary_term = $wpseo_primary_term->get_primary_term();
$term = get_term( $wpseo_primary_term );
if (is_wp_error($term)) {
// Default to first category (not Yoast) if an error is returned
$category_display = $category[0]->name;
$category_link = get_category_link( $category[0]->term_id );
} else {
// Yoast Primary category
$category_display = $term->name;
$category_link = get_category_link( $term->term_id );
}
}
else {
// Default, display the first category in WP's list of assigned categories
$category_display = $category[0]->name;
$category_link = get_category_link( $category[0]->term_id );
}
// Display category
if ( !empty($category_display) ){
if ( $useCatLink == true && !empty($category_link) ){
$output_category = '<div class="taxonomy-category wp-block-post-terms"><a href="'.$category_link.'">'.htmlspecialchars_decode($category_display).'</a></div>';
} else {
$output_category = '<div class="taxonomy-category wp-block-post-terms">'.htmlspecialchars_decode($category_display).'</div>';
}
}
return $output_category;
}
}
add_shortcode( 'yoast-primary-category', 'get_yoast_primary_cat' );
The problem is this does not work on any pages using the query block. It works ok on my single.html template because the ID is in the loop.
But I need to somehow add the post ID to the $category = get_the_category();
in my shortcode but doesn't appear to be a way to do that. Will your plugin provide a solution and if so, how?
Thank you!
@bradhogan The MFB works with all kinds of custom fields, not just ACF. For your use case, you can simply add the MFB block into your custom Query Loop, then choose field type as meta and field name as ‘_yoast_wpseo_primary_category’ (I think this is the meta field that stores the primary category, but I have not tested it myself). That setting will display the category name. To display it as a term link, you just need to add a filter to format the output of the block. Please read through the plugin description for more details here.
@Mr2P would there be a way to output a shortcode instead? Because in some cases if the meta field (_yoast_wpseo_primary_category) does not exist, then the shortcode I created will instead display the first available category for the post.
@Mr2P got it! thanks for making this plugin!
Just for reference..
add_filter( 'meta_field_block_get_block_content', function ( $block_content, $attributes, $block, $post_id ) {
$field_name = $attributes['fieldName'] ?? '';
// Replace `your_field_name` with your unique name.
if ( '_yoast_wpseo_primary_category' === $field_name ) {
$block_content = do_shortcode('[yoast-primary-category]');
}
return $block_content;
}, 10, 4);
@bradhogan I’m happy to hear that you resolved the issue. If you need any assistance in the future, please don’t hesitate to create a support ticket on the plugin page.
Phi.
@Mr2P got it! thanks for making this plugin!
Just for reference..
add_filter( 'meta_field_block_get_block_content', function ( $block_content, $attributes, $block, $post_id ) { $field_name = $attributes['fieldName'] ?? ''; // Replace `your_field_name` with your unique name. if ( '_yoast_wpseo_primary_category' === $field_name ) { $block_content = do_shortcode('[yoast-primary-category]'); } return $block_content; }, 10, 4);
Or just run any shortcode if you enter a shortcode as meta field name:
` add_filter( 'meta_field_block_get_block_content', function ( $block_content, $attributes, $block, $post_id ) {
$field_name = $attributes['fieldName'] ?? '';
// If the $field_name is in [], run the shortcode if ( substr( $field_name, 0, 1 ) === '[' && substr( $field_name, -1 ) === ']' ) { $block_content = do_shortcode( $field_name ); }
return $block_content;
}, 10, 4); ` @Mr2P , do you think you can add a native shortcode support as well?
I’m still not entirely sure why this ticket was closed at all. Passing the Current Post ID to the Query Block is still something that should be done natively.
I’m still not entirely sure why this ticket was closed at all. Passing the Current Post ID to the Query Block is still something that should be done natively.
It was closed by the user the opened it. https://github.com/WordPress/gutenberg/issues/35676#event-5483647680 The reason wasn't explained, but someone should probably open a new issue for the same topic.
@Mr2P , do you think you can add a native shortcode support as well?
@slapic Sorry for my late reply. You can extract your snippet to a tiny addon plugin so that you can input shortcodes in the field name without native support shortcodes. Please make sure the priority is higher than 10, maybe PHP_INT_MAX.
guys do we have any solution yet for this?
I am trying to include a human time (1 hour ago) in the query loop block. trying to build a custom loop in block editor.
shortcode not working in it.
this is the shortcode I made very simple
function post_time_elapsed_shortcode() {
// Check if inside a post loop. If not, return nothing.
if (!in_the_loop()) {
return '';
}
return esc_html( human_time_diff( get_the_time('U'), current_time('timestamp') ) ) . ' ago';
}
add_shortcode('time_elapsed', 'post_time_elapsed_shortcode');
this is the loop;
result :(
Still an issue. Frustating that WordPress has broken the basic understanding of how a query loop should function. We should be able to access post data from within the loop without doing backflips. Some (many?) of us don't want to build everything using blocks within a query loop... or have to create our own blocks to display content. We shouldn't have to edit core to make this happen. We shouldn't have to implement a hacky filter. It. should. just. work.
I need this ASAP, any workarounds please?
I need this ASAP, any workarounds please?
You can use my plugin Meta Field Block. It works great inside a Query Loop. Since version 1.2.3, it supports running shortcodes as well.
I need this ASAP, any workarounds please?
You can use my plugin Meta Field Block. It works great inside a Query Loop. Since version 1.2.3, it supports running shortcodes as well.
+1 MFB is one of the "missing features" of WordPress. This is exactly how core should provide this functionality.
I need this ASAP, any workarounds please?
You can use my plugin Meta Field Block. It works great inside a Query Loop. Since version 1.2.3, it supports running shortcodes as well.
+1 MFB is one of the "missing features" of WordPress. This is exactly how core should provide this functionality.
Meta Field Block is using rest api, no magic
+1 This is an issue today, May 2024! And haven't found a solution yet. I'm using quey loop block and I just need the post IDs per item in the loop ...
I'm happy to share that I've found a solution for this problem! It doesn't require "hacking" the core of WordPress, it is lightweight, universal, easy to use, and configurable, relying solely on native approaches. Additionally, it ensures that everything works as originally intended where this solution isn't needed. I don't want to duplicate my original comment on this, so here is the link instead:
Hello, I would like to output an ACF field in each query loop item. Therefore I need the post_id of the current item. How can I get that?
Thanks, Julian