Update 2 – December 24, 2018
The ability to run WordPress trunk from /src
has been restored as of today (see this post on the WordPress Make blog). I plan to update this post to account for the changes.
Update – December 19, 2018
I encountered an issue after updating Valet+ past version 1.0.23. I have since updated my LocalValetDriver.php
file. The updated version is reflected below.
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.
Background
There have been some big changes recently to the structure of the core WordPress codebase. These changes came about because of a need to reorganize the various bits of JavaScript in WordPress core, while also introducing a proper build flow. These changes came about in ticket #43055, and for all the details and discussion, I recommend reading about it on WordPress Trac.
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 /build
directory.
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.
Folder Structure
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
The 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.
The 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.
Custom Files
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.
Config files
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:
Valet driver
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.
The LocalValetDriver::serves()
method is simple; we always return true
because this driver will always be handling requests for this site. This also stores the root path to the site, so we can make use of it later in the loadServerEnvironmentVariables()
method (explained below).
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 LocalValetDriver::isStaticFile()
method is important for any WordPress core files to be mapped correctly. This method will attempt to use the URI as-is, but then will fall back to looking within the WordPress directory for the appropriate file.
The final method is LocalValetDriver::loadServerEnvironmentVariables()
. First, a caveat: this method is only available in Valet+ as of version 1.0.19. It is being considered for Valet, but has not yet been implemented. This method will allow you to create a filed named .env.valet
in the root of your site with custom environment variables. If you can’t think of why you might need this, that’s OK. It’s not needed for everyone.
WP CLI
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 wp/build/
.
Running Tests
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 content/plugins/action-scheduler/
directory:
WP_TESTS_DIR="$(realpath ../../../wp/tests/phpunit/)" phpunit@5 -c tests/phpunit.xml.dist
And just like that, my tests run!
Conclusion
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.
Leave a Reply