10

All the documentation I've encountered discusses overriding pluggable function via your plugin.

What if you're doing theme development instead?

My functions.php requires another file that overrides the get_user_by() function, defined in pluggable.php.

If I omit the if( function_exists() ) call I get the "Cannot redeclare..." error.

If I include the if( function exists() ) call, then I get no error, but of course my function is then ignored, since the pluggable version exists.

Based on Dominic's awesome post on the WordPress startup order, it's clear that pluggable.php is loaded before your theme's functions.php and so forth, so that explains the error.

So the question is - how can you take advantage of that nice pluggable architecture from within a theme, without resorting to writing plugins which then must be bundled or installed with the theme?

Further notes: So it appears that the argument is that themes should not be trying to do what plugins do. But that argument is over four years old (according to the 4-digit trac number). I'd love to hear from some heavy hitters whether this philosophy still applies, given the complex topology of today's theme development landscape. I'd like to believe we've evolved since then.

Context: I'm developing a one-off CMS solution for a customer, with a lot of custom metadata, customization of the Admin back-end, the login/authentication process, the works. And of course, there's the design component - that's where the theme part comes in. Fact is, these are simply not reusable components - they will never apply to another client, they will never be put under GPL and open sourced, and they are most certainly not to be distributed / installed on other WordPress deployments. At best there are some best practices I will leverage on future projects, but that will be strictly a reference / copy-paste job.

This does not sound like a use case for plugins to me. The theme is installed, maybe a child theme of Twenty Eleven, maybe a standalone, its functions.php calls in a boatload of includes, each handling a different aspect of the CMS in question. Then the theme template files use custom 'template tags' that are defined in the includes. I don't want to have theme files with dependencies on some plugin or other being activated, etc. It just doesn't make sense to build complexity into the system. Sure, I can put it in the must-use plugins folder, but that still feels like a hack - right now, everything that has to do with the customizations made for this project are contained in wp-content/themes/my-theme/. I don't also want to have to consider searching for stuff in some plugins folders as well.

Don't get me wrong. I love plugins and I use them and write them. And I do use plugins in conjunction with this sort of highly customized theme development when the plugin is third-party and represents best practices far beyond what I could possibly roll out in a reasonable timeframe. But when I need to modify core functionality for a one-off scenario, I turn to action hooks, filter hooks, and I'd like to be able to rely on pluggable functions for the user and authentication side of things too.

2

3 Answers 3

10

If you are building this for a single client, you should absolutely take advantage of mu-plugins.

There are a lot of things in WordPress that you can't do in functions.php. Pluggable functions is one of them, but more obvious, a number of hooks (both actions and filters) fire before functions.php. In some cases, these hooks even fire before regular plugins, which then requires you to use mu-plugins or a network-activated plugin. In still other cases, even a mu-plugin is too late. Perhaps you need something in sunrise.php. Or even something (a constant or otherwise) in wp-config.php.

I would rather add some hooks to pluggable functions, than to make it easier to override them. We are not likely to ever again have another pluggable function — they pre-date hooks and I've almost never seen a situation where there is advantage to them over a good old-fashioned (new-fashioned?) hook.

I still agree, six years later, with Andy Skelton — "There are many differences between a theme's functions file and a plugin. Let's keep it that way."

That all aside, a change like this could never happen. It would break a lot of things. Countless themes call functions in the body of functions.php that would result in a fatal error if pluggable.php hadn't already loaded — like current_user_can(), or wp_create_nonce(). They'd all fail. And it'd break plugins, too, which normally could start calling these functions on plugins_loaded. (Just move pluggable.php lower in wp-settings.php and I bet half of core would break — or at the very least, the customizer would.)

Finally, there's the inevitable idea that a theme could include a separate file like pluggable.php that we could load as early as we load plugins, and therefore could override pluggable functions. Aside from this being a bad idea (see the first four paragraphs of this comment), it would still not be compatible, because up until the setup_theme hook, one could override which theme is to be loaded by filtering stylesheet and template values.

Unfortunately, this just isn't tenable given how WordPress is architected. The good thing is, there are countless (better) ways to do it.

(Originally posted here: http://core.trac.wordpress.org/ticket/2479#comment:5)

1
  • Appreciate you taking the time to cross-post your answer here. Now that you've explained it, I see things your way. Makes sense. Thanks!
    – Tom Auger
    Commented Jun 21, 2012 at 13:35
5

In the context of a once-off project, it is absolutely appropriate to drop must-use code into mu-plugins. If "having it all in once place" is a concern, just make a symlink in the theme dir to the mu-plugins drop-in, so it'll show up when searching the theme directory.

1
  • Mark, thanks for the suggestion about the symlink. Although it doesn't help with migration, it can be very convenient when developing.
    – Tom Auger
    Commented Jun 21, 2012 at 13:36
0

I can't think of a way to accomplish this, too early in loading sequence.

The closest to sane solution would be adding custom include to wp-config.php (by code or asking user to), but comparing to that bundling plugin would probably make more sense.

1
  • Yeah, tell me about it.
    – Tom Auger
    Commented Jun 20, 2012 at 18:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.