Update: Since I first published this, I’ve renamed the framework Bamboo, and I’ve dumped the workbench project I was building in favor of a simpler, Composer
WordPress is the best content management system money can’t buy—it’s beautiful, it’s user-friendly, it’s mature, extensible, stable, well-supported, and free. If you agree, then you should keep reading.
Writing code for WordPress sucks—the extensibility of the thing is amazing, but every other PHP framework* I’ve worked with has enabled greater expression. Whether or not you agree, I think you should keep reading.
* At this point you might be thinking, “Well, Aaron, perhaps the problem is that you keep trying to treat WordPress like a framework—it’s not a framework, it’s an extensible CMS. Stop trying to make WordPress bend over backwards.”
And if that is what you’re thinking, I think you’re wrong. Keep reading.
WordPress can do more; we just need better tools
Before I tell you why I think you’re wrong and how I think we can make WordPress even more amazing than it already is, let me show you this:
What you’re watching there is a short screen capture of me using a social auth plugin I wrote just this week.
Now that, in and of itself, is not remarkable, though I would like to give myself mad props for the minimalism in the UI.
Here’s why this is remarkable:
- It was a quick build: The plugin took less than a day to write
- It’s tiny: so far, less than 600 lines of code, discounting dependencies
- It’s configurable: everything is in the environment, where it should be
- It supports almost 100 OAuth providers, including the big 3 social networks
And the most remarkable thing of all: it’s based on Laravel.
- It’s a plugin: it’s portable1, and can access 100% of WordPress APIs
- It’s Laravel: if you can do it with Laravel, now you can do it in WordPress2
- There are zero hacks: WordPress can still be updated, and so can Laravel
In other words: this is cake, and we get to eat it too.
So what can Laravel do?
Ask not what Laravel can do for you, but what can you do with Laravel?
The Laravel framework is for Web Artisans.
If you value elegance, simplicity, and readability, then you’ll love working in Laravel. And if you value those qualities in code, then you probably also dislike developing for WordPress, especially if what you’re building is more than just a customization of a beautiful CMS.
Out of the box, Laravel provides fluent APIs for database access and schema generation, caching, file system access (local and remote), session management, validation, encryption, event broadcasting, notifications, payment processing, social authentication, and full-text search—everything you need to build beautiful, functional solutions to challenging problems.
And what Laravel can do only begins in this core. Just like for WordPress, there is a large and growing community of people building and extending what Laravel can do. They’ve even created some CMSs of their own—perish the thought.
All that was missing to bring Laravel to WordPress was a bridge.
I want your next WordPress plugin to be Illuminated by Laravel
So I wrote a plugin framework, and a workbench for making it easier to jump-start your next project, whether that’s a plugin or a theme. At time of this writing, these tools are proofs of concept—you’ll find that more documentation is needed, and some more bridgework, too.
But it does work. Just follow these instructions to get started. You’ll find them to be opinionated—just like me.
Every Illuminated Plugin is a thin bootstrapping layer wrapped around a Laravel Service Container—just like every Laravel and Lumen application, but without having to be the only container in the request. This means that you can have more than one Illuminated Plugin installed and involved in a single request.
So how do these plugins look in practice?
Well, let’s say, for the sake of example, that you want to run a database query using Laravel’s query builder every time WordPress is initialized. It’s a stupid example, but it would look something like this:
Note that there’s no call to WordPress’
add_action() function hanging out anywhere. That’s because the
onInit method is automatically discovered and hooked for you. All you have to do is follow a simple pattern: action hooks begin with
on, and filter hooks begin with
Want to trigger some code every time the
plugins_loaded event is invoked by WordPress? Just add a method named
onPluginsLoaded to your Plugin class. That’s all you have to do! #winning
Ready for a more sophisticated example?
Say that you want to send a message to Slack every time a WordPress Post is updated. In practice, that would look something like this:
There’s some magic going on there that isn’t fully explained by a code snippet, but you get the picture. The code is elegant, simple, and readable. And the more I work with it, the better it gets.
So let’s add social auth to WordPress.
To better prove these concepts, I wrote the plugin I talked about at the beginning of this post. auth-plugin-wordpress builds on Laravel Socialite.
Socialite “provides an expressive, fluent interface to OAuth authentication” for the big social networks and for many other providers, and “it handles almost all of the boilerplate social authentication code you are dreading writing.” And there’s a small army of people making sure those providers are up-to-date.
All I had to do was setup two routes: one for starting the OAuth request, and one for processing the return. And all you have to do is use my plugin.
But speaking of setting up routes—so far, my favorite feature of this framework is the fluent syntax for extending WordPress’ REST API routes and defining rewrite rules that aren’t simply fancy ways of adding data to the Posts query:
What you can’t do.
I know there are going to be some limitations—things that you can’t do with Laravel because of the context of running on top of a WordPress stack. But so far I’ve only run into one.
If you’re writing Illuminated WordPress Plugins for distribution, you can’t use Laravel’s Facades. In Laravel, Facades are a bit of syntactic wizardry that allow you to use a static method invocation to call an instance of the underlying provider stored inside the Service Container.
You can’t do that in our plugins because each plugin is a Service Container—with more than one Service Container in play for any request, by default no one Service Container is considered an authority, and so the Facades aren’t useful.
For example, it’s not OK to do this—in fact, by default, it won’t work at all:
But, if the code you’re writing is for a single, customized WordPress site and isn’t intended for distribution, then it’s all good—you can use Facades!
All you have to do is invoke
$plugin->enableFacades() in your plugin’s bootstrap.php file, and just like that, your plugin’s container will be considered the default Service Container—the one from which all facades would pull their referenced providers.
This has been a really heady post—my first in a long time. Thank you for taking the time to read it, and I hope that if you have constructive feedback for me that you’ll leave it in a comment below, or e-mail it to aaron [at] collegeman [dot] net.
If you’re a WordPress or Laravel developer, and you’d like to lend a hand to making this effort all it can be, please do not hesitate to e-mail me at the address above.
The next things on my roadmap are:
I need to put some finishing touches on auth-plugin-wordpress; the last step in registration is an e-mail that contains a link for setting an account password—that feels like the wrong thing to do in the context of social auth.
Then I need to add more features to the workbench project—chief among them the ability to package Illuminated plugins for distribution in the WordPress plugin repository.
The next step will be to finish writing the plugin framework, maximizing the availability of Laravel features to the WordPress codebase—I am most excited about integrating the full-text features of Laravel Scout; I think that will be an incredibly useful think to offer to all sorts of different applications.
Then I’m doing to document the shit out of everything.
Finally, I’m going to take this best-of-breed toolset, and I’m going to build some truly remarkable things. But what I’m really excited about is seeing what you build with WordPress and Laravel—what problems will you try to solve?
1 I still need to make it a little bit easier to package and distribute these plugins the traditional way—I can, and I will.
2 I do mean everything in Laravel is available, but there are some notable differences, primarily in routing, which I have built a custom solution for (discussed below). Also, some more exploration is going to be necessary (and fun!) to make sure things like Laravel’s events system are working well.