Advanced Custom Fields: use a repeater subfield in a shortcode to output another subfield

3 weeks ago 21
ARTICLE AD BOX

First of all, since you are willing to use the native acf shortcode to output values coming from a Repeater field, it's worth nothing that's not supported:

https://www.advancedcustomfields.com/resources/shortcode/#limitations

Only works for simple text based values

Now if you really wanted to go that route without overriding the native shortcode, it was enough to enable the shortcode and just use it mapped to basic Text fields. But since that's not what you are actually asking, let's see how to create a custom shortcode and how to map it to your own function that will retrieve the value of the requested field[key] from the given postId.

The shortcode registration — in functions.php

https://developer.wordpress.org/reference/functions/add_shortcode/

We'll call our shortcode acf_lookup just not to override the native one in case you were going to activate it (despite being disabled by default for good reasons), and we'll bind it to our custom function acf_repeater_lookup_shortcode that we'll implement with the next step.

We need first to define the function we are going to bind to our new shortcode and that will be in charge of retrieving the value corresponding to the given key in the my_repeater field in the given post_id; and then register our new shortcode.

What you were missing was while looping each row of the field, if the current key does match the field_name you are trying to map, then pick that value and print it, otherwise continue. And as a side note, have_rows expects the name of the field that I hardcoded in the function as my_repeater (keep that in mind!) and the id of the post.

Just add the followings to your functions.php:

function acf_repeater_lookup_shortcode( $atts ) { // Merge the shortcode attributes provided by the user with defaults. // If 'field_name' or 'post_id' are missing from the shortcode, they default to empty string. $atts = shortcode_atts([ 'field_name' => '', 'post_id' => '', ], $atts); // Sanitize the 'field_name' attribute — strips any dangerous/extra whitespace or characters. $field_name = sanitize_text_field( $atts['field_name'] ); // Cast 'post_id' to an integer — ensures it's a valid number and not a string or malicious input. $post_id = intval( $atts['post_id'] ); // If either attribute is missing or invalid, bail out early and return nothing. if ( ! $field_name || ! $post_id ) return ''; // Ask ACF: does the repeater 'my_repeater' on post $post_id have any rows? if ( have_rows( 'my_repeater', $post_id ) ) { // Loop through each row of the repeater one by one. while ( have_rows( 'my_repeater', $post_id ) ) { // Advance ACF's internal pointer to the current row, // making its subfields available via get_sub_field(). the_row(); // Read the value of the 'key' subfield in the current row. $key = get_sub_field( 'key' ); // Read the value of the 'value' subfield in the current row. $value = get_sub_field( 'value' ); // Check if this row's 'key' matches what was passed in the shortcode. if ( $key === $field_name ) { // Match found — return the corresponding 'value', safely escaped for HTML output. // 'return' also stops the loop immediately since we found what we needed. return esc_html( $value ); } // No match on this row — the while loop continues to the next row. } } // No matching key was found in any row — return empty string so nothing is printed. return ''; } add_shortcode( 'acf_lookup', 'acf_repeater_lookup_shortcode' );

Using the shortcode

Since I followed your syntax matching the name of the arguments you chose (and pay attention you were maybe inspired by the names you found on the native one, but field_name there was actually field!) to use the shortcode just do:

[acf_lookup field_name="Key1" post_id="123"]
Read Entire Article