• I have created shortcode that collects vale from ACF custom field of a post.

    It first gets post id using get_the_ID() adn then get_field() to collect custom field value.

    Shortcode works fine in single post template.

    However, when used in archive template, instead of collecting value for each post in a loop, it seems collects value form the first post and shows the same value for all posts on a page. If there are more pages, then on each page it gets value of the first post on a page and shows the same value for rest of the posts on page.

    I di some debugging and it seems although shortcode is placed in Post Tenlate block within QueryLoop, it’s code is executed only once on a page, bit value is displayed for each post in loop.

    I am puzzled, how this can be…

Viewing 10 replies - 1 through 10 (of 10 total)
  • get_the_ID() will only return the first Post ID in the loop. You need to use another method in your loop, such as
    global $post;
    $post_id = $post->ID;

    This works for me:

    <?php while (have_posts()) : the_post(); ?>
    <?php $current_id = get_the_ID(); ?>
    <?php echo $current_id ?>
    <?php endwhile; ?>
    Thread Starter pedjas

    (@pedjas)

    Thanks!

    global $post;
    $id = $post->ID;

    did not work.

    It does the same, executes only once in a template, collects value from the first post in loop, and use that value for all posts.

    Second example is not applicable to my case. I have Block Theme and Block QueryLoop. I have to use hooks or shortcodes to get what I want.

    If it was not Block Theme, it would be easy.

    • This reply was modified 1 year, 4 months ago by pedjas.

    The shortcode is not actually being executed within the Query Loop Block so you don’t have access to the output variables. It is executed by the containing page, which is why the ID for the containing page appears repeatedly, not the IDs for the posts that were outputted by the Query Loop Block.

    Thread Starter pedjas

    (@pedjas)

    I guess that is viable explanation.

    Too bad, as making blocks is so complicated…

    Here’s a method I made, but it’s not exactly what I would consider ideal.

    <script type="text/javascript">
    <!--
    	jQuery(function($){
    	   $("li.wp-block-post").each(function(index, element){
    	       $($(this).attr('class').split(' ')).each(function() { 
                 c=this.split('post-');
                 if(c[1]){
                    if($.isNumeric(c[1])){
                      console.log('Post ID: ' + c[1]);  
                    } 
                 }
               });
            });   
    	   });
    -->
    </script>

    This extracts the Post ID from CSS class name for each list element, and sends it to the console.

    I placed this code in the theme footer and was able to get all of the Post IDs from the Query Loop Block.

    From this information, I can use AJAX to get the custom fields from each post from the Query Loop Block.

    I can also use this information, and JavaScript, to customize the Query Loop Block content on the fly, without the need for extending the Query Loop Block.

    I like this method, but I think getting the Post ID this way is clumsy and maybe risky.

    Alternatively, that JavaScript I posted also works fine if you use it in a custom HTML block on the same page as the Query Loop Block.

    Also, the only risk factor that I am aware of from this method is that you need to be sure to sanitize the Post ID before you use it in a database query, etc. But that should always be done anyway.

    I only mentioned risk because anytime we go from server-side to client-side there’s an increase in risks. Security has to be paramount. Sanitize everything.

    I’ll show you how I’ve taken this script and used it in a shortcode.

    Plugin

    add_shortcode('my-shortcode', 'my_shortcode_function');
    function my_shortcode_function($atts){
        $hello = $atts['hello'];
        $nonce = wp_create_nonce('my-nonce');
        $output = "<script type='text/javascript'>
    <!--
    	jQuery(function($){
    	   $('li.wp-block-post').each(function(index, element){
    	       $($(this).attr('class').split(' ')).each(function(){ 
                 var c = this.split('post-');
                 if(c[1]){
                    if($.isNumeric(c[1])){
                      console.log('Post ID: ' + c[1]);
                      var your_php_file = '../my-file.php', 
                          response = '',
                          data = {
                            nonce: '" . $nonce . "',
                            post_id: c[1]
                          };
                      jQuery.post(your_php_file, data, function(response){
                          if(response != ''){
                            console.log('Result: ' + response);
                          } else {
                            console.log('Error');
                          }
                      });
                    } 
                 }
               });
            });   
    	   });
    -->
    </script>";
        $output .= $hello;
        return $output;
    }

    That script creates the shortcode my-shortcode which calls my_shortcode_function.

    The $atts attribute is available for passing values from the shortcode to the script.

    I included an $atts example where the text “Hello!” is handed to the script, and then it’s handed back to the page where it is subsequently printed.

    wp_create_nonce creates a security token for the JavaScript AJAX request.

    my-file.php contains the script that fetches the Post meta and returns it to the JavaScript.

    my-file.php

    <?php
    
    require('wp-load.php');
    
    if(!wp_verify_nonce($_REQUEST['nonce'], 'my-nonce') || !isset($_REQUEST['post_id']) || !is_numeric($_REQUEST['post_id'])){
       die('Validation Failed'); 
    }
    
    echo get_post_meta($_REQUEST['post_id'], 'my_custom_field_name', true);
    
    ?>

    This PHP script loads the WordPress environment, validates the security token, nonce, and checks if the post_id variable is in fact a number.

    If the submission was valid, get_post_meta() retrieves the specific custom field, “my_custom_field_name

    Each Post/Page is given the custom field, “my_custom_field_name“. The values will be printed to the console when this script runs.

    Shortcode

    [my-shortcode hello="Hello!"]

    This shortcode is placed only once in the same Page/Post as the Query Loop Block.

    I hope you find this information helpful.

    Thread Starter pedjas

    (@pedjas)

    Thanks I wil try this but I do except another kind of aproblem. My site content is in Cyrillic script and i created plugin that runs transliteration to Latin per request. But transliteration can be done only on generated HTML content. Any content generated by JavaScript is done after transliteration is done and it cannot be transliterated.

    Anyways, this is interesting so I will try it.

    All this complications are result of lack or natural support for displaying custom fields in WP core. I have to make custom code just to be able to get values for displaying.

Viewing 10 replies - 1 through 10 (of 10 total)
  • The topic ‘How ti get values from posts in archive loop?’ is closed to new replies.