As anyone whose work in WordPress whose tried to create their own shortcodes knows, it can be a nuisance. Trying to come up with unique names for the shortcodes so as not to cause conflicts, supporting nested shortcodes, etc., etc. It can be a challenge.
Instead of using functions, however, I’ve started using enclosures and classes. Such a class itself registers shortcodes which it can have embedded. And to overcome the actual shortcode tag itself conflicting – I’ve found you can “namespace” those, too. Here’s an actual example:
<?php namespace sunsport\shortcodes; /** * This class provides the functionality for creating the HTML structures for * the frontpage tiles * * @author ncrause */ class Tiles { public function __construct() { add_shortcode('sunsport:tiles:create', array(&$this, 'create')); wp_enqueue_style('sunsport-tiles', '/css/tiles.css'); } public function __destruct() { remove_shortcode('sunsport:tiles:create'); } public function start($atts = array(), $content = null) { include __DIR__ . '/fragments/tiles/start.php'; } public function create($atts = array(), $content = null) { extract(shortcode_atts(array( 'href' => '/', 'img' => '/img/image_missing.png' ), $atts)); include __DIR__ . '/fragments/tiles/create.php'; } } add_shortcode('sunsport:tiles:start', function($atts, $content) { $instance = new Tiles(); return $instance->start($atts, $content); });
So, what we have here is a shortcode “sunsport:tiles:start” which creates an instance of our class. That instantiation registers a new shortcode “sunsport:tiles:create”, which would be unavailable otherwise, thus we avoid have to check to make sure it’s properly enclosed in a parent “start” shortcode, and we gracefully deregister it at the end of the run.
It’s probably worth include the “fragments/tiles/start.php” file just for reference:
<div class="sunsport-tiles"> <?= do_shortcode($content) ?> <div class="clear"></div> </div>
And here’s the actual usage:
[sunsport:tiles:start] [sunsport:tiles:create img="img/tiles/photo_button01.png" href="/products"]Vinyl Lettering[/sunsport:tiles:create] [sunsport:tiles:create img="img/tiles/billboard_photo.png"]Billboard[/sunsport:tiles:create] [sunsport:tiles:create img="img/tiles/photo_button03.png"]The Company[/sunsport:tiles:create] [/sunsport:tiles:start]
There’s is one word of warning – do not do a naming convension like this:
- parent shortcode – sunsport:tiles
- child shortcode – sunsport:tiles:create
The child shortcode will never fire. For some reason, it seems WordPress doesn’t actually read in the full shortcode in this scenario – instead of “sunsport:tiles:create” firing, WordPress will simple re-run “sunsport:tiles”.
That caveat aside, I find this feels a lot cleaner and less collision-prone than other examples I’ve seen.