Roots Discourse

Creating a shortcode using a controller

I have a Controller to show my social media icons in my footer. I’m looking to extend this functionality and create a shortcode that I can use on any page/post. Here’s what I have so far to display my social media icons in my footer.blade.php template.

in /app/Controllers/App.php:

public function social_media_icons() {

    // Get all social media icon fields
    $social_media_icons = get_field('social_media_icons', 'options');

    // Set up array
    $data = [];

    // Loop through each block
    foreach ($social_media_icons as $social_media_icon) {

            // Do any logic for this component here

            $block = (object) [
                'profile_url' => $social_media_icon['profile_url'],
                'font_awesome_icon' => $social_media_icon['font_awesome_icon'],
                'social_media_platform' => $social_media_icon['social_media_platform'],
            ];
            
            array_push($data, $block);
        
    }

    $data = (object) $data;

    return $data;
}

In /resources/views/partials/social-media-icons.blade.php:

@if('social_media_icons')
<ul class="social">
  @foreach($social_media_icons as $social_media_icon)
  <li>
    <a href="{{ $social_media_icon->profile_url }}" title="{{ $social_media_icon->social_media_platform }}">
    {!! $social_media_icon->font_awesome_icon !!}
    <span class="sr-only">{{ $social_media_icon->social_media_platform }}</span>
    </a>
  </li>
  @endforeach
</ul>
@endif

In /resources/views/partials/footer.blade.php

@include('partials/social-media-icons')

Now I’m looking to make this into a shortcode that I can call our social media icons on any page/post. I wasn’t able to find anything on this when searching. Any ideas?

You could use the template() function to pipe the output of your partial through a shortcode, i.e.:

// functions.php or something
add_shortcode('social', function($atts) {
   $social_media_icons = get_this_data_somehow();
   return App\template(
      'partials.social-media-icons', 
      ['social_media_icons' => $social_medial_icons]
   );
});

How you get_this_data_somehow() is kind of up to you. Personally I would refactor it out of your controller, because that’s going to be a wierd place to have that logic if

  1. You need it somewhere else (i.e., a shortcode)
  2. It’s not dependent on data only available in the controller

I’d probably move your “get social media data” logic to functions.php or somewhere else, and then call it wherever you need that data:

// functions.php or something
function get_social_media_data()
{
    // Get all social media icon fields
    $social_media_icons = get_field('social_media_icons', 'options');

    // Set up array
    $data = [];

    // Loop through each block
    foreach ($social_media_icons as $social_media_icon) {

            // Do any logic for this component here

            $block = (object) [
                'profile_url' => $social_media_icon['profile_url'],
                'font_awesome_icon' => $social_media_icon['font_awesome_icon'],
                'social_media_platform' => $social_media_icon['social_media_platform'],
            ];
            
            array_push($data, $block);
        
    }

    $data = (object) $data;

    return $data;
}

// controllers/App.php
public function social_media_icons() {
   return \App\get_social_media_data();
}

// function.php or something
add_shortcode('social', function($atts) {
   return App\template(
      'partials.social-media-icons', 
      ['social_media_icons' => get_social_media_data()]
   );
});

I use this method and it works well for multiple shotcodes:

Thank you, @alwaysblank and @Andrew_Scofield! This solution works perfectly :slight_smile: