1

I have been looking into setting up WordPress and its plugins and themes using composer. I notice alot of the tutorials around have composer installing wordpress into its own sub directory for example /wp and the themes, plugins, must use plugins to a completely different directory like /content. Is there a reason why it doesn't use /wp/content for the plugins/themes/ect and make /wp the web root? I noticed composer seems to properly install everything this way, so it there something I am missing?

EDIT: I should clarify that I am aware that updating core will remove the content directory, however all the plugins/themes are also installed by composer and I don not rely on it for persistent upload storage, I offload my media uploads to S3. So with that in mind is there any other downside to using this setup? Because I really do prefer the more traditional file structure.

  • I very highly recommend Roots Bedrock for doing this, and in their documentation they explain why it makes sense. – Moshe Katz Mar 8 at 17:13
1

You can do whatever suits your needs, such as still using composer but configuring your implementation to place the directories back into the root along with core, however the primary purpose in having core stand-alone from other directories is for separation of concerns that are not dependant upon one another sharing the same path.

The wp-content directory can already be moved outside of the installation root, natively, using constants without composer.

For example:

define( 'WP_CONTENT_DIR', dirname(__FILE__) . '/blog/wp-content' );
define( 'WP_CONTENT_DIR', dirname(__FILE__) . '/blog/wp-content' );

define( 'WP_CONTENT_URL', 'http://example/blog/wp-content' );

define( 'WP_PLUGIN_DIR', dirname(__FILE__) . '/blog/wp-content/plugins' );
define( 'WP_PLUGIN_URL', 'http://example/blog/wp-content/plugins' );
define( 'PLUGINDIR', dirname(__FILE__) . '/blog/wp-content/plugins' );

define( 'UPLOADS', 'blog/wp-content/uploads' );

So even core acknowledges that the relationship between core and wp-content is not dependant upon wp-content being a child of the root installation.

If WordPress did not have 20 years of legacy behind it, I doubt very much that the folder structure we see today would remain.

The composer way of doing it has the opinion that they should be separate because as we've progressed and the web, tooling and applications we build become more complex we realise that there's somethings we don't want exposed to the root, often for security reasons but also for logical reasons (i.e. application-domains).

I've personally used:

This is from one of WPSE's very own Giuseppe Mazzapica / @gmazzap housed under the wecodemore imprint founded by another of WPSE's very on Franz Josef Kaiser / @unserkaiser and which has received contributions from other WPSE members and the greater WP at large.

We all tend to agree that this separation of concerns is a good way to go about structuring our applications, but again, you're not bound to it.

Using wpstarter for example, you can achieve what you want by altering the composer file to specify your desired paths.

From:

"extra": {
    "wordpress-install-dir": "public/wp",
    "wordpress-content-dir": "public/content",
    "..." : "...",
    "installer-paths": {
        "public/content/plugins/{$name}": [
            "type:wordpress-plugin"
        ],
        "public/content/mu-plugins/{$name}": [
            "type:wordpress-muplugin"
        ],
        "public/content/themes/{$name}": [
            "type:wordpress-theme"
        ]
    }
}

To:

"extra": {
    "wordpress-install-dir": "public/wp",
    "wordpress-content-dir": "public/content",
    "..." : "...",
    "installer-paths": {
        "public/wp/content/plugins/{$name}": [
            "type:wordpress-plugin"
        ],
        "public/wp/content/mu-plugins/{$name}": [
            "type:wordpress-muplugin"
        ],
        "public/wp/content/themes/{$name}": [
            "type:wordpress-theme"
        ]
    }
}

composer excerpt shortened for brevity

...and that should do what you need.

See:

| improve this answer | |
  • The separation of concerns would be nice to be able to do, but my point is since the wp-content must be web accessible in order to make the wp directory the webroot it is necessary to make content a subdirectory of wordpress. I did some quick tests to see if this would work and from what I can tell it should. I just wanted to make sure I wasn't missing some technical gottcha with such a setup. – Paul37349 Mar 10 at 11:48
  • Not sure I totally understand the issue here however from what I gather you are concerned simply about the naming convention and if you move that convention back into what we normally see in a default install, except with custom folder name structure. I see no problem there with what you are trying to do. If all directories have the correct permissions (and files too) create the naming structure as you see fit, nested or not. You should be fine. – Adam Mar 10 at 13:54
1

Putting the webroot in a desired directory is just following best practices. Since you want to have certain things outside of the webroot to not be accessible via http://example.com/sensitive-info or http://example.com/some-script for example. Think of .env files, custom Composer scripts, CI config, or the vendor and/or bin directory.

When it comes to plugins or themes it is that unfortunately WordPress puts custom, contrib and core plugins and themes in the same directories. So when you now put your custom and contrib plugins and themes in these directories and then do composer update and the WordPress core gets updated these directories get reset. Same for the content directory. Furthermore it's that everything that is a Composer dependency – the core – should be kept outside the Git repo. At best you commit only the composer.json and composer.lock files and your custom plugins and themes.


  • Check Smashing Magazine's blog post on Using Composer With WordPress for more detailed information.

  • I once built leymannx/wordpress-project as a proof-of-concept to have Composer and the more traditional file structure both at once. I achieved that with custom Composer scripts which symlink everything it its place. Look how lightweight it actually is. And when you do it right you can simply delete the whole webroot directory and just do composer install and everything will be wired up again.

| improve this answer | |
  • 1
    Nice, will have to check out your lib. There's always room for more and I agree there's no one package fits them all. – Adam Mar 8 at 9:05
  • @Adam – Thanks for the edit! I wish there would be at least one standard template the greater community could agree on. At best WordPress core would at least separate core, contrib and custom themes and plugins somehow... – leymannx Mar 8 at 9:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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