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: Current post ID #35676

Closed
julian-stark opened this issue Oct 15, 2021 · 42 comments
Closed

Query Block: Current post ID #35676

julian-stark opened this issue Oct 15, 2021 · 42 comments
Labels
[Type] Help Request Help with setup, implementation, or "How do I?" questions.

Comments

@julian-stark
Copy link

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

@skorasaurus skorasaurus added the [Type] Help Request Help with setup, implementation, or "How do I?" questions. label Oct 15, 2021
@ntsekouras
Copy link
Contributor

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
Copy link
Author

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

@ntsekouras
Copy link
Contributor

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
Copy link
Author

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
Copy link
Contributor

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
Copy link
Author

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
Copy link
Contributor

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

@julian-stark
Copy link
Author

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
Copy link

jb510 commented Dec 26, 2021

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
Copy link

morksinaanab commented Dec 27, 2021

@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
Copy link

jb510 commented Dec 27, 2021

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
Copy link

lgladdy commented Jan 12, 2022

👋 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
Copy link

scott8035 commented Apr 8, 2022

@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
Copy link

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
Copy link

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
Copy link

spacedragn commented Apr 11, 2022

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
Copy link

scrobbleme commented May 16, 2022

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
Copy link

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
Copy link

Bellian commented Aug 8, 2022

The problem is already adressed here #37754 (comment) 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.

@MarieComet
Copy link
Contributor

This is still an issue with WP 6.1.1.

@bradhogan
Copy link

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
Copy link

spacedragn commented Apr 14, 2023

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
Copy link

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
Copy link

kaiakonsap commented May 29, 2023

@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
Copy link

Mr2P commented May 31, 2023

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
Copy link

bradhogan commented Jun 15, 2023

@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
Copy link

Mr2P commented Jun 16, 2023

@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
Copy link

@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
Copy link

@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
Copy link

Mr2P commented Jun 16, 2023

@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
Copy link

slapic commented Nov 4, 2023

@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
Copy link

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
Copy link

jb510 commented Nov 8, 2023

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. #35676 (comment) The reason wasn't explained, but someone should probably open a new issue for the same topic.

@Mr2P
Copy link

Mr2P commented Nov 8, 2023

@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
Copy link

sinanisler commented Dec 17, 2023

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
Copy link

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
Copy link

AlkoKod commented Feb 16, 2024

I need this ASAP, any workarounds please?

@Mr2P
Copy link

Mr2P commented Feb 16, 2024

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
Copy link

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
Copy link

d9media commented Apr 13, 2024

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
Copy link

+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
Copy link

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)

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

No branches or pull requests