Creating Short Codes

 

Short codes are introduced into WP via plugins. The template code provides you with some options to help manage complexity around short codes.

Option 1: you can create a short code that calls a function on your XXX_Plugin class

Option 2: you can create a short code in its own PHP class, by extending XXX_ShortCodeLoader. If you are going to write a lot of code & functions, it may be a better idea to separate that PHP code into another file rather than cram it all into the same XXX_Plugin.php file.

Option 3: like option 2, but with some support to only add its needed script and styles on pages where the plugin actually is called. This is done by extending XXX_ShortCodeScriptLoader.

Option 1: Short Code as Function on XXX_Plugin.php

To create a simple short code, find the addActionsAndFilters() and put in a call to add_shortcode that points to a function that you add.

1
2
3
4
5
6
7
public function addActionsAndFilters($atts) {
    add_shortcode('say-hello-world', array($this, 'doMyShortcode'));
}
 
public function doMyShortcode() {
    return 'Hello Word!';
}

Add [say-hello-world] to a post to invoke the short code. The $atts variable will be an array of the short code attributes. See add_shortcode.

NOTE: notice how the short code function returns its output string instead of echoing it. This is important. If you echo it, it will appear at the top of the page, not in the post where the short code is inserted. Be sure to return output only. If you need to use echo, then buffer the output and return it using the following technique.

1
2
3
4
5
6
7
public function doMyShortcode() {
    ob_start();
    echo 'Hello World!';
    $output = ob_get_contents();
    ob_end_clean();
    return $output;
}

Option 2: Short Code as a Subclass of XXX_ShortCodeLoader

If your short code implementation involves a lot of code, or you have a lot of short codes, then you may find making a short code be its own class in its own file easier to manage. To do this, create a new file in your plugin directory. For this example, we create an XXX_HelloWorldShortCode.php file (remember “XXX” is the prefix used on the files for your plugin. This is just a convention to avoid class name collisions with other plugins).

1
2
3
4
5
6
7
8
9
10
11
include_once('XXX_ShortCodeLoader.php');
 
class XXX_HelloWorldShortCode extends XXX_ShortCodeLoader {
    /**
     * @param  $atts shortcode inputs
     * @return string shortcode content
     */
    public function handleShortcode($atts) {
        return 'Hello World!';
    }
}

Remember to return instead of echo output as described in the note under Option 1. The $atts variable will be an array of the short code attributes. See add_shortcode.

Register the short code in the XXX_Plugin.php file, addActionsAndFilters() function:

1
2
3
4
5
public function addActionsAndFilters() {
    include_once('XXX_HelloWorldShortCode.php');
	$sc = new XXX_HelloWorldShortCode();
	$sc->register('say-hello-world');
}

 

Option 3: Short Code as a Subclass of XXX_ShortCodeScriptLoader

This option works the same as Option 2 with two differences:
  • Your new short code class extends XXX_ShortCodeScriptLoader instead of XXX_ShortCodeLoader
  • You must implement an additional function in your class, addScript()

The XXX_ShortCodeScriptLoader super class helps you insert scripts only on those pages in which the short code appears. This is a somewhat imperfect solution. The problem is how WP processes pages. Ideally, we would like the short code to be able to inject scripts and styles in the HTML HEAD of the page in which it appears. But WP generates the HEAD before it ever gets to calling code associated with a short code. So any calls to wp_enqueue_script or wp_enqueue_style in your short code callback function do nothing. Your options are:

  • En-queue scripts and style that the short code needs in all pages, even those in which the short codes does not appear. This is done in the  XXX_Plugin::addActionsAndFiters() function. See Enqueueing Javascript & CSS Files
  • Inject the scripts and styles in-line where the short code appears. The problem with this is if the short code appears more than once in a page, you include things multiple times.
  • Put code in your short code callback function to include things in the footer

This XXX_ShortCodeScriptLoader employs the last option: including things in the footer. Here is an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
include_once('XXX_ShortCodeScriptLoader.php');
 
class XXX_HelloWorldShortCode extends XXX_ShortCodeScriptLoader {
 
    static $addedAlready = false;
    public function handleShortcode($atts) {
        return 'Hello World!';
    }
 
    public function addScript() {
        if (!self::$addedAlready) {
            self::$addedAlready = true;
            wp_register_script('my-script', plugins_url('js/my-script.js', __FILE__), array('jquery'), '1.0', true);
            wp_print_scripts('my-script');
        }
    }
}

Notice the static $addedAlready variable used to guard against adding the script twice. There is some code in the super class that prevents the script from being added if the short code does not appear in the page.

This technique does not work for styles. Styles seem to need to be added before the HTML that they are styling. {Anybody know a trick to make this work?}

Register the short code just as in Option 2 above:

1
2
3
4
5
public function addActionsAndFilters() {
    include_once('XXX_HelloWorldShortCode.php');
	$sc = new XXX_HelloWorldShortCode();
	$sc->register('say-hello-world');
}

 

 

  5 Responses to “Creating Short Codes”

  1. Should public function handleShortcode($atts) contain a call to self::addScript();? I find my scripts do not get added otherwise.

  2. Any tips for getting the $content into the handleShortcode($atts) function? I’ve added the variable to the function declarations in 3 files but the data remains unpopulated.

    • Got it! To add $content to shortcodes, update the following definitions:

      1. XXX_HelloWorldShortCode.php : public function handleShortcode($atts, $content) {

      2. XXX_ShortCodeLoader.php :

      public function handleShortcodeWrapper($atts, $content) {
      // Flag that we need to add the script
      $this->doAddScript = true;
      return $this->handleShortcode($atts, $content);
      }

      3. XXX_ShortCodeLoader.php : public abstract function handleShortcode($atts, $content);

      • Just a quick note on #2. It should be XXX_ShortCodeScriptLoader.php, not ShortCodeLoader.php. But good work otherwise. Totally saved me. Thanks!

  3. For option 3 is there a way to add a priority to the add_action call? I would like the En-queued scripts to happen later than they are in the footer.

    If I try to add a priority number at the end of the add_action call the code breaks (i.e.):

    public function register($shortcodeName) {
    $this->registerShortcodeToFunction($shortcodeName, ‘handleShortcodeWrapper’);
    add_action(‘wp_footer’, array($this, ‘addScriptWrapper’),100);
    }

    Thanks!

Leave a Reply to Eric Cancel reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>