WordPress / gutenberg

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

Query loop - remove current post ID for ‘related posts’ #42810

Open Humanify-nl opened 2 years ago

Humanify-nl commented 2 years ago

What problem does this address?

I think it is a very common practice to add query loops in the bottom of a single template to show ‘other/related posts’. This is currently not possible with the block.

What is your proposed solution?

In the classic approach, we could use the query argument to remove the current postID (with get_the_id) (I used this as a default for all queries).

This works because we very rarely have cases where the post(-type) or page query should include itself in the loop (correct me if I’m wrong).

Can we do this for the query-loop block? It would enable ‘related posts’ lists under any page, while omitting the post currently on screen. Without having to add another filter arg in the block settings.

ntsekouras commented 2 years ago

👋 - Actually we had a similar and not complete handling for this(for different reasons though) and removed it later.

Your use case is having a Query Loop in a template(ex. post) for related posts etc..? If it's not in a template and is in some specific post you can work around for now by adding the id in the query.exclude property. Obviously though this is not the proper solution.

For the templates use case this should be possible in server side(front end) only as we don't have a specific id in the site editor if we are editing the single-post template for example. A new property like excludeCurrentPost in Query Loop could possibly do the trick..

Do you have a work around for that in your code now? If yes, can you share?

Humanify-nl commented 2 years ago

Thank you for the info @ntsekouras,

Indeed. The idea is to do this in a single post template, it is only needed for front end.

I have not found a workaround yet, as I currently use a custom ACF block and a php query loop, and am looking for ways to do this with WP only.

I’d like to help but I’m not that familiar with creating a new property.

Humanify-nl commented 2 years ago

To continue on this:

I've found the constant QUERY_DEFAULT_ATTRIBUTES in query/variations.js

This seems to hold the query arguments. But I also see a variation that replaces this array with a new one.

So, I could register a new variation, and exclude the current post ID. There already is an exclude array in the arguments, but how to get the current post_id in there I don't know.

Furthest I get: is adding "usesContext": [ "postId" ] in the block.json and adding $block->context("post_ID") in the render_callback, but that is php.

Marc-pi commented 2 years ago

yep, a highly needed feature, to be able to make use of the Query Loop Block on all websites. Usage need : add a "You may also like" section in the bottom of a post, filtered by the same category as current the one the current article is associated to IMHO, the Query Loop block should also be extended to become the Gutenberg Swiss kniffe, like the Clickly Query Builder see https://www.youtube.com/watch?v=yRS5V34NwvU&t=547s.

mrfoxtalbot commented 1 year ago

This came up in a forums support thread, here https://wordpress.org/support/topic/query-loop-and-related-posts-exclude-current-post/

carlomanf commented 1 year ago

@Humanify-nl what is the difference between this issue and #39192?

bbertucc commented 1 year ago

I'm watching this. Hope it becomes a reality! My use case: I have a "related posts" section in a post. I set it to a related category as the current posts and I want it to include the newest posts from that category, excluding the current post.

noellesteegs commented 1 year ago

I also have a use case for this, same as OP, wanting to use it in a post template to show related posts.

chrisgresh commented 1 year ago

I'd also love to see this feature under the 'Filters' section. I'm currently including 3 'Related Posts' and using Javascript to hide the current post if it displays on itself.

supernovia commented 1 year ago

We have a request in our forums for this, too: where the sidebar shows a query loop with latest posts, it's a bit silly to show the post the user is currently viewing, but I see no way to exclude the current post ID.

Humanify-nl commented 1 year ago

While I’d love for the query loop to have the old arguments array back as a filter, this needs an interface in the current paradigma, and I assume this is why fine control of queries is still not a thing.

The easiest solution for this issue, is to make it default for every query block to exclude the post with the current post ID. I can’t think of a context where this would not work or cause problems.

dinhtungdu commented 9 months ago

Another (PHP) workaround is filtering query_loop_block_query_vars to modify the query arguments for the query loop block. We can distinguish the block to modify by setting a custom block name of the Post Template block (not Query Loop) (class also works) and then use that name to target the right query to modify.

Here is an example to exclude the current post. Note that post__not_in can be slow.

add_filter( 'query_loop_block_query_vars', function( $query_vars, $block ) {
    if ( isset( $block->attributes['metadata']['name'] ) && $block->attributes['metadata']['name'] === 'Related Post Template' ) {
        $query_vars['post__not_in'] = array( get_the_ID() );
    }

    return $query_vars;
}, 10, 2 );

We're not limited to simple modification. If plugins can provide IDs of related posts, we can feed them to the query through post__in to have better and more relevant recommendations.

lunule commented 7 months ago

Thanks @dinhtungdu - I could use your snippet to remove the current post from a custom query loop block instance on a single post page/template.

I couldn't make the metadata version work though, only using a custom class.

To help folks needing an example:

  1. Add a custom class name in your template/template part/pattern to your wp:post-template block within the wp:query block:
<!-- wp:post-template {"className":"fse-pilot--read-next"} -->
(...)
  1. Then the current post can be excluded, specifically for this very query, by using the following function:
function fse_pilot_remove_current_from_queries( $query_vars, $block ) {

    if ( 'fse-pilot--read-next' === $block->parsed_block['attrs']['className'] )
        $query_vars['post__not_in'] = array( get_the_ID() );

    return $query_vars;

}
add_filter( 'query_loop_block_query_vars', 'fse_pilot_remove_current_from_queries', 10, 2 ); 
efu98 commented 2 months ago

Hello! Can i work on this ?

ramonjd commented 2 months ago

A pretty naive take, but I'm wondering if it could be achieved by reading a (new) Query block exclude_posts attribute from the Post Template block?

Putting the challenge of a useable UI in the Query block aside, the Post Template block has access to the Query block query param attributes in $block->context['query'].

So it could skip rendering block content if an excluded post is matched:

        if ( in_array( $current_post_id, $query_post_id_to_exclude ) ) {
            continue;
        }

https://github.com/WordPress/gutenberg/blob/b74aeada2b26566ee071a0f973272f1861d86307/packages/block-library/src/post-template/index.php#L112-L112

Hello! Can i work on this ?

Hi @efu98 👋🏻

No need to ask! I'm sure if you can get a PR up there'll be folks to help review 🙇🏻

Thanks

richtabor commented 2 months ago

Seems like it could work.

Marc-pi commented 2 months ago

hi, naive question, but did you have a look at @ryanwelcher 's AQL plugin (https://wordpress.org/plugins/advanced-query-loop/) ? as long as i know he's member of the core team and automatician, maybe he can advised something too, based on experience :-) maybe part of his code can be merged into the default distro (or as feature plugin).

g-elwell commented 2 months ago

Hey all - I've implemented this feature previously as an extension of the core query block. I've opened a PR to share my solution, as I think this is something that should be part of core, it's so commonly needed https://github.com/WordPress/gutenberg/pull/64916