In summary, I’ve used custom config files and a custom Valet driver to enable running a development site using the Trunk version of WordPress. Feel free to skip down to the “Folder Structure” and “Custom Files” sections below if you don’t need any background on why this fancy setup is needed.
For some of the codebases I work on, running unit tests involve having access to the core WordPress unit tests. Prior to the change mentioned above, it was possible to run a fully-functional version of WordPress from the
/src directory. That is no longer possible, and WordPress can only be run from the
Initially, I thought I would be able to keep my custom files in
/src, use the build script to have them copied over to the /build directory, and then continue on my way. But, in addition to the drawbacks of this method (such as a very long build process, or even timeouts), it is now no longer possible due to ticket #44256.
There’s been much discussion around the best solution going forward, and the best option is to take advantage of two native WordPress constants to use a custom content directory.
I’m using Valet+ for my local development environment, and put all of my individual development sites in my
~/Sites directory. This particular folder will be named
prospress, and it will be served on the prospress.test domain. I’ll explain this in subsequent sections, but for now here’s what my final folder structure will look like (some files were excluded because they aren’t relevant):
prospress/ ├── LocalValetDriver.php ├── content/ │ ├── index.php │ ├── mu-plugins/ │ ├── plugins/ │ ├── themes/ │ ├── upgrade/ │ └── uploads/ ├── wp/ │ ├── build/ │ ├── src/ │ ├── tests/ │ ├── tools/ │ ├── wp-config.php │ └── wp-tests-config.php └── wp-cli.yml
content/ directory in this folder follows the same structure as your normal
wp-content/ folder in WordPress. This is where all of my development files live.
wp/ directory is where the WordPress trunk checkout lives. My intent with this directory is to only set up a
wp-config.php file and
wp-tests-config.php file here.
As mentioned above, I only want to customize the various config files. We’ll go through each of the various files to explain what they are doing and why they are needed.
Here is what my
wp-config.php file looks like:
The main thing of note are these two lines:
define( 'WP_CONTENT_DIR', dirname( __DIR__ ) . '/content' ); define( 'WP_CONTENT_URL', 'https://<PROJECT FOLDER NAME>.test/content' );
These lines are what tell WordPress to use
prospress/content/ instead of
prospress/wp/build/wp-content/ for all of my plugins, themes, etc. It also tells WordPress to use
/content/ as the URI, instead of
/wp-content/. The only reason for the latter change is to keep the same folder name.
The same settings have been put in place in my
wp-tests-config.php file, which will be used when running Unit Tests. One notable difference is that I have configured a different database for use with tests, to make sure my data is not overwritten. Here’s what that file looks like:
With that change in place, I also need to make sure that my server knows how to properly route requests to the
/content directory. This is where the
LocalValetDriver.php file comes into play. Valet and Valet+ both allow a custom driver that lives in the root of your site. This custom driver can ensure that Valet serves the files for your site correctly. Here’s what my
LocalValetDriver.php file looks like:
This custom driver extends the native
WordPressValetDriver class that comes as part of Valet. The native driver provides most of the functionality we need, and then we can incorporate our own tweaks to make sure our setup works correctly.
LocalValetDriver::serves() method is simple; we always return
true because this driver will always be handling requests for this site. Next is the
LocalValetDriver::frontControllerPath() method. This method determines whether the request should be routed to the
content/ directory or the
wp/build/ directory. This is important to make sure our content is accessible to the browser. Once the determination has been made, we allow the parent method to take over.
The final method,
LocalValetDriver::isStaticFile() is not strictly needed, but I have included it as a fallback in case there are any stray files that need to be redirected to the correct location.
To make WP CLI use easier from any directory within this site, I’ve added a
wp-cli.yml file to the root of the site. Its contents are quite simple:
This serves to tell WP CLI where the root path to WordPress can be found. With this in place, running WP CLI commands from the
content/plugins/ directory will work just as well as running commands from inside
The final portion of this setup involves running tests for some of my plugins, since that was the whole point in the first place. Plugins that work with WordPress core unit tests will usually support the
WP_TESTS_DIR environment variable. This variable is expected to point to the location of
tests/phpunit/ inside the WordPress checkout repository. This is something that you could define globally if you want, using a file like
~/.profile or something similar. But I’m choosing not to define it globally, and so I’ll need so define it when running tests.
As an example, I have the Action Scheduler plugin installed in
content/plugins/. I also have a copy of PHPUnit 5.7 that I can run for tests that need that version of PHPUnit. This is what my command looks like when running tests from within the
WP_TESTS_DIR="$(realpath ../../../wp/tests/phpunit/)" phpunit@5 -c tests/phpunit.xml.dist
And just like that, my tests run!
This took quite a bit of tinkering to get running correctly, and in the end it was far more simple than I expected. My original process was a hacked together way of running WordPress from the
src/ directory, despite the steps the Core team has taken to prevent this. In the end, I have something simple and useful, and it is easy to replicate.
The idea for utilizing the custom
WP_CONTENT* constants was pulled from WordPress Core slack, where I believe I first saw it mentioned by Andrew Ozz here: https://wordpress.slack.com/archives/C02RQBWTW/p1527605380000214.
Questions? Comments? Ideas for improvement? Feel free to comment below, or reach out on Twitter, where I’m @JPry.