A composer.json
example
Table of contents
- The code
composer.json
step by step- WP Starter specific configuration
- A look at the folder structure
The code
The sample composer.json
below is not very different from what can be used in a real-world WP Starter powered website:
{
"name": "my-company/my-project",
"type": "project",
"description": "My Project Description",
"license": "proprietary",
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": ">= 7.4 < 8.3",
"composer/installers": "^2.2",
"wecodemore/wpstarter": "^3",
"roots/wordpress": "~6.1.1",
"inpsyde/wonolog": "^2",
"wpackagist-theme/twentytwentythree": "1.0.*",
"wpackagist-plugin/wordfence": "^7.9",
"wpackagist-plugin/memcached": "^4.0",
"wpackagist-plugin/batcache": "^1.5"
},
"config": {
"optimize-autoloader": true,
"allow-plugins": {
"composer/installers": true,
"wecodemore/wpstarter": true,
"roots/wordpress-core-installer": true
}
},
"extra": {
"wordpress-content-dir": "public/wp-content",
"wordpress-install-dir": "public/wp",
"installer-paths": {
"vendor/{$vendor}/{$name}": [
"wpackagist-plugin/memcached",
"type:wordpress-dropin"
],
"public/wp-content/mu-plugins/{$name}": [
"type:wordpress-muplugin",
"wpackagist-plugin/batcache"
],
"public/wp-content/themes/{$name}": [
"type:wordpress-theme"
],
"public/wp-content/plugins/{$name}": [
"type:wordpress-plugin"
]
}
},
"repositories": [
{
"type": "composer",
"url": "https://wpackagist.org"
}
]
}
For readability’s sake, WP Starter specific configuration will be placed in separate wpstarter.json
file that could look like this:
{
"content-dev-dir": "./",
"dropins": [
"./public/wp-content/mu-plugins/batcache/advanced-cache.php",
"./vendor/wpackagist-plugin/memcached/object-cache.php"
],
"wp-cli-commands": "./scripts/wp-cli-commands.php",
"env-bootstrap-dir": "./config",
"early-hook-file": "./bootstrap.php",
"env-dir": "./env",
"db-check": "health"
}
But the exact same configuration could have been placed in a extra.wpstarter
object in composer.json
with exact same result.
composer.json
step by step
"name"
, "type"
, "description"
and "license"
, "minimum-stability"
, and "prefer-stable"
root properties are Composer settings not specific to WP Starter. Please refer to Composer documentation if not familiar with it.
Require
require
section of composer.json
is where we tell Composer what packages we need, and in which version.
"composer/installers"
is a Composer plugin that provides custom installers for application or framework specific files. In our case, requiring this package we ensure WordPress plugins and themes packages will be placed in the target wp-content folder instead of in the standard “vendor” folder.
"wecodemore/wpstarter"
is the present package.
The two packages above are the only two required packages in a WP Starter powered website.
"roots/wordpress"
is an unofficial WordPress package maintained by Roots. Even if this is not required, nor is the only way to put WordPress core on the project, this is right now the most common way (with several millions of downloads) to deal with core installations in projects managed by Composer.
The package is actually no more than a “wrapper” package to provide two different packages: the roots/wordpress-core-no-content
that provides no more than WordPress core code and a roots/wordpress-core-intaller
that is an installer Composer plugin that tells Composer where to place WordPress core files and folders.
"inpsyde/wonolog"
is just an example of a library (not a plugin) that we might want to add to our website. Because it is available on Packagist we just add it to requirements. It can depends on other dependencies, that can depend on other dependencies, and so on. Composer will recursively discover all the dependencies and install everything for us. If there’s a conflict in dependencies version we will discover those on install, so conflicting code can not ever be released.
"wpackagist-theme/twentytwentythree"
is the official 2023 theme. It does not support Composer, but we can require it via WordPress Packagist, because we have included that in our "repositories"
setting.
"wpackagist-plugin/wordfence"
is an example of a plugin we might want to add to our website. We also get it via WordPress Packagist.
"wpackagist-plugin/batcache"
is a plugin that is also available on WordPress Packagist. It represents a special case. Looking at its source it contains both a MU plugin (batcache.php
) and a dropin (advanced-cache.php
). Moreover, Composer type is wordpress-plugin
because the wp.org repository only allows for regular plugins, not MU plugins nor dropins. We will see how, despite the messy situation, with a very minimum configuration WP Starter will handle it perfectly, placing everything in the right place without any manual intervention nor custom scripts.
"wpackagist-plugin/memcached"
is a dropin. Once again, it has the wordpress-plugin
type because of wp.org limitation. And once again we can get this working easily with minimum configuration.
Config
In recent Composer versions, Composer plugins must be enabled. The config.allow-plugins
property is used for that scope. See documentation.
Extra
extra
is the composer.json
that Composer reserves for Composer plugins configuration. And that is exactly what we using it for: providing configuration for the 3 plugins we have:
- WP core installer
- WP Starter
- Composer installers
WP core installer configuration
WP core installer is an “installer Composer plugin”. It tells Composer where to place the packages of type "wordpress-core"
, that are not supported by Composer installers. By default the plugin tells Composer to install WordPress in the ./wordpress
directory, but provides the extra.wordpress-install-dir
to customize it.
In our sample, we are telling to place WP in the folder public/wp
, because having a “public” folder and WordPress folder in it.
WP content configuration
WP content folder is indirectly defined by the setting we use for plugin and themes via "extra.installer-paths"
path (more on this below). In fact, if we tell Composer to put plugins in public/wp-content/plugins
we are kind of implying that public/wp-content
is the content folder.
However, WP Starter needs the content folder to be explicitly declared.
The way we inform WP Starter about the location of WP content folder is extra.wordpress-content-dir
setting that is designed to be symmetrical to wordpress-install-dir
and so placed outside extra.wpstarter
that is where all the other WP Starter settings resides.
Composer Installers configuration
We require Composer Installers to allow WordPress plugins, themes, MU plugins, and dropins to be placed inside WP content folder instead of default vendor folder.
By default, installers tells Composer to place those WordPress-related packages in the /wp-content
folder inside the project root folder.
However, that does not work for us: first because we are customizing the content folder (placing it outside of WP core folder) and then because we are also customizing WP core folder.
Luckily, Composer Installers supports configuration via the "extra.installer-paths"
entry. See documentation.
With the configuration in our sample file we are telling Composer Installers to place:
- Packages of type
"wordpress-dropin"
, as well as thewpackagist-plugin/memcached
(that we know is also a dropin with a wrong Composer type) package to the vendor folder. The dropin files are put in place by WP Starter, but we need Composer to put them somewhere, and here we tell it to put them the vendor folder like any other non-WordPress dependency. - Packages of type
"wordpress-muplugin"
, as well as thewpackagist-plugin/batcache
package (that we know is also a MU plugin with the wrong type) in the folderpublic/wp-content/mu-plugins/{$name}
, where$name
will be replaced by the package name, e. g. “batcache” forwpackagist-plugin/batcache
(where “wpackagist-plugin” is the vendor); - Packages of type
"wordpress-theme"
in the folderpublic/wp-content/themes/{$name}/
, which is where WordPress will look for them. - Packages of type
"wordpress-plugin"
in the folderpublic/wp-content/plugins/{$name}/
, which is where WordPress will look for them.
It is worth noting that while this setup works for plugins and themes, it does not work out of the box for MU plugins and dropins. WordPress will look for MU plugins directly placed inside wp-content/mu-plugins/
(no sub-folders) and dropins needs to be directly inside wp-content/
.
WP Starter handles this issue for us.
The MuLoaderStep
takes care of creating a MU plugin that acts as a “loader” for other MU plugins that Composer placed in sub-folders of wp-content/mu-plugins
, and the DropinsStep
takes care of moving the dropin files directly into wp-content
.
It is worth noting that the "wpackagist-plugin/batcache"
contains both a MU plugin and a dropin, and WP Starter handles this situation pretty well with a single line of configuration. More on this below.
Repositories
In the sample composer.json
we used "repositories"
setting to tell Composer to use WordPress Packagist. This is a free Composer repository (maintained by Outlandish) that exposes plugins and themes available on the official wp.org repository as Composer packages.
The official Composer repository, Packagist, is already checked by Composer, so there’s no need to add it.
WP Starter specific configuration
"extra.wpstarter"
is the place for all the WP Starter configuration. However, WP Starter supports also a separate wpstarter.json
file located at project root, and that is what we are using in our sample.
The “Configuration” chapter has a detailed explanation on how that works and the “Settings Cheat Sheet” chapter lists all the available WP Starter settings.
Below there is the a step by step explanation of just the settings used in our sample wpstarter.json
.
Please note that all the settings are optional.
content-dev-dir
The “WP Starter Steps” chapter has a detailed explanation of what “development content” means in WP Starter.
In a nutshell, those are themes, plugins, MU plugins, and dropins that are placed in the same repository of the project, but are kept outside of WP content directory because that contains 3rd party dependencies and having those in separate folder makes VCS handling easier.
By default, WP Starter expects those files and folders to be placed in a /content-dev
folder inside root. By setting content-dev-dir
to "./"
we are telling WP Starter that the “development content” parent folder is project root.
Which means, for example, that any plugin inside /plugins
will be symlinked at /public/wp-content/plugins
where WordPress will found them. Same goes for themes, MU plugins, dropins, and translation files.
In our example, the wonolog-configuration.php
file that is located in /mu-plugins
will be placed by WP Starter in /public/wp-content/mu-plugins
where WordPress will find it. That way we can ignore the /public
folder in our VCS, but keep wonolog-configuration.php
under version control, as we surely want.
dropins
The package "wpackagist-plugin/batcache"
will be placed in ./public/wp-content/mu-plugins/batcache/
thanks to the Composer installers settings. That path works for the MU plugin file it actually ships (thanks to the loader that WP Starter creates), but not for the dropin file the package also provides.
In the same way, "wpackagist-plugin/memcached"
will be placed in ./vendor/wpackagist-plugin/memcached/
but we need the object-cache.php
it contains into the wp-content root.
The dropins
settings in our wpstarter.json
sample is an array of dropin file paths that WP Starter has to place in the proper folder. By simply listing the source paths WP Starter will know what to do, and everything will be setup without any additional script or manual intervention.
wp-cli-commands
There’s an entire documentation chapter, “WP CLI Commands”, that explains the ins and outs of running WP CLI commands via WP Starter (and why it might be worth to do it) .
So we are not going to explain the purpose of wp-cli-commands
again here, we can just say that the file located at ./scripts/wp-cli-commands.php
will return an array of commands to be passed to WP CLI for execution.
We don’t have to worry about installing WP CLI: WP Starter will do that for us if needed.
env-dir
This is the folder where WP starter will look for .env
files. If not provided, it will be the project root. Refer to the “Environment Variables” chapter for details.
env-bootstrap-dir
Besides environment variables, WP Starter also allows for environment-specific PHP files. These are PHP files named per environment, e. g. production.php
. These file are loaded very early, and can be used to configure WordPress per environment.
The “WordPress Integration” chapter has more details about this.
By default, these files are searched in the same folder that contains .env
files, but this setting allows use to set a different folder.
early-hook-file
This is a file that is loaded by WP Starter very early, and can be used to add early configuration. Even if WordPress is not fully loaded (we we can’t directly use most of the WP functionalities) we can use WP actions and filters.
The “WordPress Integration” chapter has more details about this.
db-check
By default, when WP Starter founds database credentials in the environment, it checks for the database to be reachable. By setting this configuration to health
we are telling WP Starter to do a more advanced health check using mysqlcheck
binary.
A look at the folder structure
By looking at the sample composer.json
above, we can guess what could be a possible folder structure of the project before and after Composer and WP Starter runs, with highlight of the files and folders created by WP Starter:
(Note: most of files in WP root has been removed for readability sake)
In between, there’s Composer and WP Starter running, with this output:
When WP Starter finishes, if webroot is correctly pointing to /public
, and the .env
file contains the necessary DB configuration, then our website is already working.
Next: WP CLI Commands