$conf, $runtime; function_exists('chdir') AND chdir(APP_PATH); $r = 'mysql' == $conf['cache']['type'] ? website_set('runtime', $runtime) : cache_set('runtime', $runtime); } function runtime_truncate() { global $conf; 'mysql' == $conf['cache']['type'] ? website_set('runtime', '') : cache_delete('runtime'); } register_shutdown_function('runtime_save'); ?>How to apply action the_post to the post that is only being mainly displayed|Programmer puzzle solving
最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

How to apply action the_post to the post that is only being mainly displayed

matteradmin10PV0评论

I'm trying to write an action that will modify some WooCommerce product on its display.

This is my simple code

function do_some_modifications($post)
{
    if (is_singular('product')) {
        // do some action
    }
    return $post;
}
add_action('the_post', 'do_some_modifications');

But the page contains two related products and "the_post" is called for them as well. How can I avoid running that code for additional products displayed on the main product page?

Thank you!

I'm trying to write an action that will modify some WooCommerce product on its display.

This is my simple code

function do_some_modifications($post)
{
    if (is_singular('product')) {
        // do some action
    }
    return $post;
}
add_action('the_post', 'do_some_modifications');

But the page contains two related products and "the_post" is called for them as well. How can I avoid running that code for additional products displayed on the main product page?

Thank you!

Share Improve this question edited Jun 23, 2014 at 19:12 Konstantin Bodnia asked Jun 23, 2014 at 13:11 Konstantin BodniaKonstantin Bodnia 1732 silver badges6 bronze badges
Add a comment  | 

5 Answers 5

Reset to default 1

Okay. Here we go!

I needed this to be implemented within only one plugin, not inside the template.

So I found out how to get the ID of current post outside the loop. The great function get_queried_object() and get_queried_object_id() will seal the deal!

It might not seem the quickiest way (it queries the database) but in my case it is a perfect solution since I'm running this code not for every page and not every time it's loaded.

And the final code is

function do_some_modifications($post)
{
    if (is_singular('product') and get_queried_object_id() == $post->ID) {
        // do some action
    }
    return $post;
}
add_action('the_post', 'do_some_modifications');

replace

    if (is_singular('product')){
      //  do some action
    }

with

    if (is_singular('product') && is_main_query()){
      //  do some action
    }

The simplest way to implement it would be to add the callback before main loop in template and remove after. Not too tidy from template perspective however.

Working purely with hooks you might want to check it if the post is present in $wp_query->posts, however that would misfire on duplicates.

In the past I remember doing this by adding custom marker property to the post object, but that was before WP_Post class was introduced and I am not sure it's viable technique anymore.

In this scenario, for this Stack question asked, the magic built in in_the_loop() does the job for me:

function do_some_modifications($post){
    if(is_singular('product') && in_the_loop()) {
        // do some action
    }
}
add_action('the_post', 'do_some_modifications');

You can skip return $post as this action is passing $post by reference.

I think the do_action('the_post') is the way to go here, not fibbling around inserting template actions, specially not woocommerce, they have templates for everything and changing them all the time.

I had a similar situation when my official plugin should do stuff before a shared template is called. Here I dont know in advanced what template the Theme would use, so I needed exactly as in this case, target the archive product listing, but not related product listings below or other widgets that may use the same template.

In case some other resourcing about this, to target sidebars only, set the conditional the opposite way !in_the_loop() and you may have to examine the $post before you do your stuff

The simplest and most reliable way I can think of, is using the second parameter of the the_post action:

function do_some_modifications( $post, $query ) {
    if ( $query->is_main_query() && $query->is_singular( 'product' ) ) {
        // do some action
    }
}
add_action( 'the_post', 'do_some_modifications', 10, 2 );

Some notes:

  1. The second parameter of the filter callback provides the actual WP_Query object that is currently processed.

  2. Also, the_post is an action and therefore does not need a return value. Instead of returning the $post value, you can directly modify the $post variable (it is a reference to the actual object that WordPress uses)

  3. When you use the function is_singular() it will always check the main WP_Query object. If you want to check the query that's currently processed by the_post then you need to use $query->is_singular().

Post a comment

comment list (0)

  1. No comments so far