phpwordpressshortcode

Wordpress shortcodes pass array of values


I am creating some WordPress short codes aimed at providing internal navigation on a page (one page with a lot of content sections and it own menu).

This is what I have:

//menu
function internal_menu($atts) {
  extract(shortcode_atts(array(
   'href1' => '#jl1',
   'href2' => '#jl2',
   'href3' => '#jl3',
   'href4' => '#jl4',
  ), $atts));
  return '<div id="internalPageMenu">
    <ul>
        <li><a href="' . $href1 . '"><i class="fa fa-bars"></i>link 1</a></li>
        <li><a href="' . $href2 . '">link 2</a></li>
        <li><a href="' . $href3 . '">link 3</a></li>
        <li><a href="' . $href4 . '">link 4</a></li>
    </ul>
    </div>';
}
add_shortcode('internal-menu', 'internal_menu');

//menu target
function internal_menu_target($atts) {
  extract(shortcode_atts(array(
   'id' => 'jl1',
   'text' => '',
   ), $atts));
   return '<h3 id="' . $id . '">' . $text . '</h3>';
}
add_shortcode('internal-menu-target', 'internal_menu_target');

And using this in my Wordpress admin panel:

[internal-menu]
[internal-menu-target id="jl1"]
Some content
[internal-menu-target id="jl2"]
...etc...

How do I make the menu dynamic (not restricted to the number of items it can have)? For example the short code would be:

[internal-menu targets="jl1, jl2, jl3, jl4, jl5, ...etc..."]

Solution

  • foreach would be your answer here. It will be the easiest and cleanest in my opinion. Before I give you a code example, lets analyze your code and look at all your flaws and how we will correct them

    FLAWS

    Lets tackle the first shortcode: (PLEASE NOTE: All the code below is untested. It might be buggy or have syntax errors)

    internal-menu

    //menu
    function internal_menu( $atts ) 
    {
        $attributes = shortcode_atts(
            array(
               'href' => '',
             ), 
            $atts
        );
    
        $output = '',
        // Check if href has a value before we continue to eliminate bugs
        if ( !$attribute['href'] )
            return $output;
        // Create our array of values
        // First, sanitize the data and remove white spaces
        $no_whitespaces = preg_replace( '/\s*,\s*/', ',', filter_var( $attributes['href'], FILTER_SANITIZE_STRING ) ); 
        $href_array = explode( ',', $no_whitespaces );
    
        $output .= '<div id="internalPageMenu">';
            $output .= '<ul>';
    
                foreach ( $href_array as $k => $v ) { 
                    // From your code, link 1 is different, so I kept it as is
                    if ( $k == 0 ) {
                        $output .= '<li><a href="#' . $v . '"><i class="fa fa-bars"></i>link 1</a></li>';
                    } else { 
                        $output .= '<li><a href="#' . $v . '">link ' . ($k + 1 ) . '</a></li>';
                    }
                }
    
            $output .= '</ul>';
        $output .= '</div>';
    
        return $output;
    }
    add_shortcode( 'internal-menu', 'internal_menu' );
    

    You can then use the shortcode as follow

    [internal-menu href='jl1, jl2, jl3, jl4']
    

    internal-menu-target

    //menu target
    function internal_menu_target($atts) 
    {
        $attributes = shortcode_atts(
            array(
               'id' => '',
               'text' => '',
             ), 
            $atts
        );
    
        $output = '',
        // Check if href has a value before we continue to eliminate bugs
        if ( !$attribute['id'] || !$attribute['text'] )
            return $output;
    
        // Create our array of values
        // First, sanitize the data and remove white spaces
        $no_whitespaces_ids = preg_replace( '/\s*,\s*/', ',', filter_var( $attributes['id'], FILTER_SANITIZE_STRING ) ); 
        $ids_array = explode( ',', $no_whitespaces_ids );
    
        $no_whitespaces_text = preg_replace( '/\s*,\s*/', ',', filter_var( $attributes['text'], FILTER_SANITIZE_STRING ) ); 
        $text_array = explode( ',', $no_whitespaces_text );
    
        // We need to make sure that our two arrays are exactly the same lenght before we continue
        if ( count( $ids_array ) != count( $text_array ) )
            return $output;
    
        // We now need to combine the two arrays, ids will be keys and text will be value in our new arrays
        $combined_array = array_combine( $ids_array, $text_array );
        foreach ( $combined_array as $k => $v )
            $output .= '<h3 id="' . $k . '">' . $v . '</h3>';
    
        return $output;
    }
    add_shortcode('internal-menu-target', 'internal_menu_target');
    

    You can use this shortcode as follow:

    [internal-menu-target id='1,2,3,4' text='text 1, text 2, text 3, text 4']