WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.49k stars 4.19k forks source link

Query Block: Current post ID #35676

Closed julian-stark closed 3 years ago

julian-stark commented 3 years ago

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

ntsekouras commented 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.

julian-stark commented 3 years ago

thank you @ntsekouras seems not too easy with my limited gutenberg dev experience 😃 would I "extend" the current query block?

ntsekouras commented 3 years ago

Can you describe more your use case? I thought you have created a block that would like to have postId inside Query Loop..

julian-stark commented 3 years ago

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.

ntsekouras commented 3 years ago

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.

julian-stark commented 3 years ago

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!

ntsekouras commented 3 years ago

I'm not sure if I was helpful here 😄 . Do you need any clarifications? If not, should we close this issue? 🤔

julian-stark commented 3 years ago

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 :)

jb510 commented 2 years ago

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.

morksinaanab commented 2 years ago

@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

jb510 commented 2 years ago

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.

lgladdy commented 2 years ago

👋 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.

scott8035 commented 2 years ago

@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.

scott8035 commented 2 years ago

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?

scott8035 commented 2 years ago

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.

@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?

spacedragn commented 2 years ago

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.

scrobbleme commented 2 years ago

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?

brandonjp commented 2 years ago

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.

Bellian commented 2 years ago

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.

Potential problem at the moment could be, that shortcodes generated in there as content might be parsed again.

MarieComet commented 1 year ago

This is still an issue with WP 6.1.1.

bradhogan commented 1 year ago

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.

spacedragn commented 1 year ago

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.

carlomanf commented 1 year ago

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.

43053 is still open and covers the same issue. Opening more issues does not accelerate the delivery of a solution, and the description of this issue is very vague and lacking in detail, while the other one has detailed reproduction instructions. It may still be a good idea to label this as a duplicate.

kaiakonsap commented 1 year ago

@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

Mr2P commented 1 year ago

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.

bradhogan commented 1 year ago

@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!

Mr2P commented 1 year ago

@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.

bradhogan commented 1 year ago

@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.

bradhogan commented 1 year ago

@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);
Mr2P commented 1 year ago

@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.

slapic commented 1 year ago

@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?

spacedragn commented 12 months ago

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.

jb510 commented 12 months ago

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 commented 12 months ago

@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.

sinanisler commented 10 months ago

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; image

result :(

image

joelmcdwebworks commented 9 months ago

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.

AlkoKod commented 8 months ago

I need this ASAP, any workarounds please?

Mr2P commented 8 months ago

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.

scrobbleme commented 8 months ago

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.

d9media commented 6 months ago

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

jabeztadesse commented 6 months ago

+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 ...

frzsombor commented 4 months ago

Solution

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:

🔗 #43053 (#issuecomment-2191491244)