'Why is this shortcode function returning the data in the wrong order?
I've been attempting to create a plugin that takes some ACF options page fields, and creates a shortcode which outputs an advertising code attached to an attribute within the shortcode
e.g. [awin id="top_banner"] would ideally return the code entered for that ID
whereas [awin id="middle_banner"] or [awin id="bottom_banner"] would return the code for each banner respectively, wherever the shortcode was found on the page.
I also added the ability to show and hide ads via an ACF boolean toggle switch.
The problem I'm having is that if an ad is hidden or the shortcode isn't within the page, it's outputting the return of this ID, but in the next instance of the shortcode (regardless of the ID)
Example
Say the "middle_banner" was hidden (or that shortcode didn't appear on the page) when you scroll down to the output for bottom_banner, you see the output for "middle_banner" instead. When you'd actually expect to see the output for bottom_banner.
Update: Oddly enough, the ID's are always correct (I've outputted this as the ID of the DIV within the return) and this always shows the correct ID from the shortcode. So it's just the returned ad code that is the issue.
My code that handles the creation of the shortcodes is below - I hope I've explained it clearly enough, I've also included the full plugin code at the end of the question if it helps for context.
// THIS LOOPS THROUGH ADS AND CREATES SHORTCODE ID's within attributes / and assigned ad code to return
// WP Shortcode to display text on page or post.
// [awin id="top_banner"]
function awin_func( $atts, $content = null, $tag = '' ) {
if( have_rows('awin_ads', 'option') ):
while( have_rows('awin_ads', 'option') ): the_row();
$embed_code = get_sub_field('awin_ad_embed_code');
$short_code = get_sub_field('shortcode');
// $short_code = preg_replace('/\s+/', '_', $short_code); /replaces spaces with underscores from input
$is_live = get_sub_field('is_showing');
$atts = shortcode_atts( array(
'id' => $short_code,
'embedded_code' => $embed_code,
), $atts, $tag );
extract($atts);
$output = '';
if($is_live == true) {
$output .= '<div id="' . $id . '" style="color:#a0a0a0; text-align:center;"> <hr><p style="margin:0;">Advert</p><br>' . $embedded_code . '<hr></div>';
}
return $output;
endwhile;
endif;
}
// this makes it init the function after wp has fully loaded
function shortcodes_init(){
add_shortcode( 'awin', 'awin_func' );
}
add_action('init', 'shortcodes_init');
?>
Funnily enough, however, when you inspect the code on the front end, the id attribute is always been passed through to the div id within the output correctly. This is what's really confusing me!
Any help would be most appreciated
Full Plugin code below:
<?php
/*
Plugin Name: Keep Digital Awin Shortcode Generator
Plugin URI: https://bitbucket.org/keep-digital/awin-plugin
description: This creates shortcodes for awin ads so you can use them around the site
Version: 1.4
Author: Dan Eland
Author URI: https://keepdigital.co.uk
License: GPL2
*/
if( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
// THIS CHECKS ACF IS INSTALLED OR USES ITS OWN LOCAL VERSION
// Optionally you can use below to check by plugin location:
// if((is_plugin_active('advanced-custom-fields/acf.php'))|| (is_plugin_active('advanced-custom-fields-pro/acf.php'))):
// Check if ACF Classes exists:
if(!class_exists('acf_pro') || !class_exists('acf')):
// Define path and URL to the ACF plugin.
define( 'MY_ACF_PATH', plugin_dir_path( __FILE__ ) . 'acf/' );
define( 'MY_ACF_URL', plugin_dir_url( __FILE__ ) . 'acf/' );
// Include the ACF plugin.
include_once( MY_ACF_PATH . 'acf.php' );
// Customize the url setting to fix incorrect asset URLs.
add_filter('acf/settings/url', 'my_acf_settings_url');
function my_acf_settings_url( $url ) {
return MY_ACF_URL;
}
// (Optional) Hide the ACF admin menu item.
add_filter('acf/settings/show_admin', 'my_acf_settings_show_admin');
function my_acf_settings_show_admin( $show_admin ) {
return false;
}
endif;
//THIS ADDS A PLUGIN OPTIONS PAGE
if( function_exists('acf_add_options_page') ) {
acf_add_options_page(array(
'page_title' => 'AWIN Ads Shortcode Generator',
'menu_title' => 'AWIN Ads Shortcode',
'menu_slug' => 'awin-ads-generator',
'capability' => 'edit_posts',
'redirect' => true
));
}
// adds custom fields to options page
if( function_exists('acf_add_local_field_group') ):
acf_add_local_field_group(array(
'key' => 'group_625809450c759',
'title' => 'AWIN Shortcode Generator',
'fields' => array(
array(
'key' => 'field_625809567e7ec',
'label' => 'AWIN ads',
'name' => 'awin_ads',
'type' => 'repeater',
'instructions' => 'Create your AWIN ad \'areas\' here. You can create as many ad \'areas\' as you require throughout the site. When you want to embed your ad \'area\' in the site, simply place your shortcode anywhere on your site within a \'text\' container, and drop the AWIN embed code into the embed code field.
You can update the ad code within any \'area\' by simply pasting new AWIN ad code into the embed field for that \'area\'
You can also hide the ad \'areas\' if you\'re between ads by using the show/hide toggle on the ad \'area\'',
'required' => 0,
'conditional_logic' => 0,
'wrapper' => array(
'width' => '',
'class' => '',
'id' => '',
),
'collapsed' => '',
'min' => 0,
'max' => 0,
'layout' => 'table',
'button_label' => '',
'sub_fields' => array(
array(
'key' => 'field_625809827e7ed',
'label' => 'AWIN Ad Embed Code',
'name' => 'awin_ad_embed_code',
'type' => 'textarea',
'instructions' => 'please paste in the Ad code from AWIN directly in here',
'required' => 1,
'conditional_logic' => 0,
'wrapper' => array(
'width' => '55',
'class' => '',
'id' => '',
),
'default_value' => '',
'placeholder' => '',
'maxlength' => '',
'rows' => '',
'new_lines' => '',
),
array(
'key' => 'field_625809c77e7ee',
'label' => 'Ad Area Name',
'name' => 'shortcode',
'type' => 'text',
'instructions' => 'What you\'d like to call your AWIN Ad Area e.g. calling it top_banner would result in creating the following shortcode: [awin id="top_banner"]',
'required' => 1,
'conditional_logic' => 0,
'wrapper' => array(
'width' => '30',
'class' => '',
'id' => '',
),
'default_value' => '',
'placeholder' => 'e.g. top_banner',
'prepend' => '[awin id="',
'append' => '"]',
'maxlength' => '',
),
array(
'key' => 'field_625819ba74b72',
'label' => 'Show / Hide Ad Area',
'name' => 'is_showing',
'type' => 'true_false',
'instructions' => '',
'required' => 0,
'conditional_logic' => 0,
'wrapper' => array(
'width' => '15',
'class' => '',
'id' => '',
),
'message' => '',
'default_value' => 0,
'ui' => 1,
'ui_on_text' => 'Ad Live',
'ui_off_text' => 'Ad Hidden',
),
),
),
),
'location' => array(
array(
array(
'param' => 'options_page',
'operator' => '==',
'value' => 'awin-ads-generator',
),
),
),
'menu_order' => 0,
'position' => 'normal',
'style' => 'default',
'label_placement' => 'top',
'instruction_placement' => 'label',
'hide_on_screen' => '',
'active' => true,
'description' => '',
'show_in_rest' => 0,
));
endif;
// THIS LOOPS THROUGH ADS AND CREATES SHORTCODE ID's within attributes / and assigned ad code to return
// WP Shortcode to display text on page or post.
// [awin id="top_banner"]
function awin_func( $atts, $content = null, $tag = '' ) {
if( have_rows('awin_ads', 'option') ):
while( have_rows('awin_ads', 'option') ): the_row();
$embed_code = get_sub_field('awin_ad_embed_code');
$short_code = get_sub_field('shortcode');
// $short_code = preg_replace('/\s+/', '_', $short_code); /replaces spaces with underscores from input
$is_live = get_sub_field('is_showing');
$atts = shortcode_atts( array(
'id' => $short_code,
'embedded_code' => $embed_code,
), $atts, $tag );
extract($atts);
$output = '';
if($is_live == true) {
$output .= '<div id="' . $id . '" style="color:#a0a0a0; text-align:center;"> <hr><p style="margin:0;">Advert</p><br>' . $embedded_code . '<hr></div>';
}
return $output;
endwhile;
endif;
}
// this makes it init the function after wp has fully loaded
function shortcodes_init(){
add_shortcode( 'awin', 'awin_func' );
}
add_action('init', 'shortcodes_init');
?>
Solution 1:[1]
Shout out to Alvin at ACF Pro support for taking the time to look over this and offer a solution:
He said "attributes are used to set a default value when an attribute is not passed as discussed at https://codex.wordpress.org/Shortcode_API."
He also has written in a bit of logic that changes the output depending on the ID, and then adds a break afterwards to stop the code once the data has been found.
Works a treat!
// THIS LOOPS THROUGH ADS AND CREATES SHORTCODE ID's within attributes / and assigned ad code to return
// WP Shortcode to display text on page or post.
// [awin id="top_banner"]
function awin_func( $atts, $content = null, $tag = '' ) {
$output = '';
/**/
$a = shortcode_atts(
array(
'id' => '',//Default value when there is no id passed
'tag' => '',//Default value when there is no tag passed
),
$atts,
$tag
);
if ( have_rows( 'awin_ads', 'option' ) ) :
while ( have_rows( 'awin_ads', 'option' ) ) :
the_row();
$embed_code = get_sub_field( 'awin_ad_embed_code' );
//var_dump( $embed_code );
$short_code = get_sub_field( 'shortcode' );
$short_code = preg_replace('/\s+/', '_', $short_code); //replaces spaces with underscores from input
$is_live = get_sub_field( 'is_showing' );
extract( $atts );
if ( $is_live == true && $a['id']==$short_code) {
$output .= '<div id="' . $short_code . '" style="color:#a0a0a0; text-align:center;"> <hr><p style="margin:0;">Advert</p><br>' . $embed_code . '<hr></div>';
break;//break after finding the data you are looking for.
}
endwhile;
endif;
return $output;
}
// this makes it init the function after wp has fully loaded
function shortcodes_init(){
add_shortcode( 'awin', 'awin_func' );
}
add_action('init', 'shortcodes_init');
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Eland |

