NB. I wrote a follow-up piece about this topic on the WP Tavern.
Yesterday, I was watching the WP Sessions stream, where Josh Pollock talked about developing WordPress plugins using Composer. Josh did a great job introducing Composer basics, however, I still feel a need to comment on one specific point that was missing in the presentation: Loading 3rd party dependencies with Composer doesn’t change the fact that WordPress isn’t designed to handle 3rd party dependencies in plugins.
Composer and WordPress
In the presentation, Josh goes over the basics of extracting parts of a plugin to a reusable Composer package. This is basically why Composer exists. In a private (or at least controlled) WordPress project, this is not a problem. This will work. Just require the dependencies and load them from the
/vendor directory. If you plan on using Composer and WordPress in a controlled environment, no problems. Check out Rarst’s site.
As Josh pointed out, the
/vendor directory should be ignored by Git, so 3rd party code won’t be committed. Except for one case: If you are distributing your plugin via WordPress.org. In that case, even though it kinda sucks and goes against the spirit of Composer, you will have to commit everything – including the 3rd party dependencies in
/vendor. But is that really a good idea?
Welcome to debugging hell
What happens when 2 plugins on WordPress.org commits the same dependency, but in 2 different versions, and both of them are installed on your WordPress site? Take a guess. It’s one of the following:
- Nothing – they just use their own included versions
- PHP will throw a fatal error, because class names will collide
- PHP will not throw an error – the autoloader will silently just include the dependency from whichever plugin is loaded first
The right answer is 3. Can you see how this can result in some pretty frustrating debugging situations?
Why does this happen?
The short answer to why this happens is that WordPress has no way of handling 3rd party dependencies. Well, it has 2: Plugins and themes. But it has no way of handling 3rd party dependencies recursively, which is what Composer relies on, i.e. dependencies of dependencies. It doesn’t matter if you use Composer or not. This is why I wrote on the Tavern that this needs to be solved in the near future.
Is it really a problem?
So, for this to be a problem, what would need to happen? All of this at the same time:
- 2 plugins needs to commit the same dependency, in 2 different versions
- I need to install both plugins on my WordPress site
- The plugin which is loaded last relies on functionality, in the other version of the dependency, that is not available or have changed enough to result in errors
Pretty unlikely. In most cases.
But what if a plugin that everyone has installed, say WordPress SEO by Yoast, included an old version of a 3rd party dependency? (they don’t, but play along). Your little plugin simply can’t be incompatible with a giant like SEO by Yoast, so there is only one option for you. You need to rely on the same old version of that dependency, since including another version could result in really strange errors.
Speaking of Yoast, in the presentation, Josh uses them as an example of someone who includes a composer package in a WordPress.org plugin. And truly enough, if you download a zipball of their plugin from WordPress.org, you will find the Composer
/vendor directory. But, there is one important point to make here. They only include their own packages (
I’m not saying that you can’t commit 3rd party dependencies to WordPress.org, but I ask you to consider these implications before your do it. Thanks for reading along.
P.s. If you are attending WordCamp Europe next week, I would love to chat about WordPress, Git and Composer!