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.