Skip to content

Instantly share code, notes, and snippets.

@HenriqueSilverio
Last active October 19, 2018 13:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HenriqueSilverio/e2f46d7831b792b7e6ce0f1ad6bbd121 to your computer and use it in GitHub Desktop.
Save HenriqueSilverio/e2f46d7831b792b7e6ce0f1ad6bbd121 to your computer and use it in GitHub Desktop.
Object-Oriented approach to create shortcodes in WordPress plugins.
<?php
namespace MyPlugin\Contracts;
interface Shortcode
{
public function getTag(): string;
public function start(): void;
public function register(): void;
public function render($atts = '', ?string $content, string $tag): string;
}
<?php
namespace MyPlugin\Shortcodes;
use MyPlugin\Contracts\Shortcode as iShortcode;
abstract class Shortcode implements iShortcode
{
private $tag = '';
public function __construct(string $tag)
{
$this->tag = $tag;
}
public function getTag(): string
{
return $this->tag;
}
public function start(): void
{
$this->register();
}
public function register(): void
{
add_shortcode(
'myprefix_' . $this->getTag(),
[$this, 'render']
);
}
}
<?php
namespace MyPlugin\Shortcodes;
use MyPlugin\Shortcodes\Shortcode;
class Login extends Shortcode
{
public function render($atts = '', ?string $content, string $tag): string
{
return 'Shortcode content here!';
}
}
<?php
namespace MyPlugin;
use MyPlugin\Shortcodes\Login;
class Plugin
{
public function start(): void
{
$shortcodeLogin = new Login('form_login');
$shortcodeLogin->start();
}
}
<?php
use MyPlugin\Plugin;
require_once 'vendor/autoload.php';
$plugin = new Plugin();
add_action('plugins_loaded', [$plugin, 'start']);
@carlalexander
Copy link

So this looks pretty good! The main thing that I noticed is:

What is the purpose of the start and register methods?

Right now, the start method calls the register method and your Plugin class calls the start method. But you could do achieve all of this by just using register everywhere. That said, I might misunderstand the purpose of the start method because there's no doc block in your iShortcode interface.

It might be worth while for you to write documentation for it. This is super important for interfaces since they're just a contract without any code. It'll also help you clarify the purpose of each method. You might even realize that you didn't need both the start and register method. 😃

@HenriqueSilverio
Copy link
Author

Hey @carlalexander, thanks for your comment! Yeah, I'll add the doc blocks soon.

For now, Iet's see if I can clarify your question, and if I'm in the "right path" or it's unnecessary.

What is the purpose of the start and register methods?

The idea of these methods is follow an kind of "Facade" pattern, like described here.

Thinking in context of an plugin a little bit "bigger" than just creating one shortcode, "catch"?

What I noticed is that, generally, I have methods like start and register in objects which hooks into WordPress.

So maybe, I can have one other interface like... Hookable with it. Anyway...

And the main Plugin class has a start method, where it'll start all the others components later.

Then the Plugin::start could be splited in something like startPublic, startAdmin, etc, according to "project specific" requirements.

So... Could I clarify? Think you this make more sense now? 🤔

@tommcfarlin
Copy link

tommcfarlin commented Oct 18, 2018

This is a great starting point :). I'd add a few notes to Carl's. They are more of less a listing of things that I notice off the bat and are my no means meant to be the way to refactor anything. Just points for consideration.

  • private $tag = ''; could probably (or perhaps should probably) be protected unless any subclass will never overwrite it.
  • ?string $content: Would this ever not be a string? I don't mean that I don't get why you did it, but I'm wondering if it needs to be simply strictly typed as string or not.
  • It looks like you can use register and remove start and put all of the logic there.
  • I would not hardcode 'myprefix_'
  • Nice use of type hinting, namespaces, and shortcodes on arrays - nice to see some modern features here 👍

Thanks for bringing this to our attention and keep up the good work :).

@HenriqueSilverio
Copy link
Author

Hi Tom, thanks for your feedback too!

?string $content: Would this ever not be a string?

I've used nullable type here, because the shortcode content sometimes could be null.
So maybe if we strictly type it as string, probably will conflict in this cases. 🤔

Again, thank you guys for the opinions. (@carlalexander, @tommcfarlin).

I really appreciate your efforts to bring attention to good practices and modern PHP on the WordPress community! 🤘

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment