I have finally cobbled together a native Windows development environment. This time—due to restrictions on access placed on the work computer, as well as donkiness from the Microsoft Store—I’ve circumvented the Windows Subsystem for Linux route I used to use.
I also like the command line more than MSIs or installer bundles. Deleting directories is easier to me than digging around in Control Panel’s uninstallers and keeping your fingers crossed.
Install the package manager
The first step is grabbing Scoop, a Windows package manager. It doesn’t have the reach of Homebrew, but their operations are very similar. Scoop requires at least version 5 of PowerShell, and you don’t have to run as administrator.
Where Scoop falls down in comparison to Brew (again, besides the range of packages available) is that it relies on Git for maintaining manifests, but doesn’t install Git itself. So, you need Git to update Scoop, but Scoop doesn’t install Git. Type this instead:
scoop install git scoop bucket add extras scoop update
Git will install 7Zip as a dependency. Scoop uses “bucket” as nomenclature for bundles of packages. Then the update process will grab the most recent manifests for the
main bucket as well as the
extras bucket we just added.
I’m only interested in PHP 8.0, so I don’t need the
versions bucket that would let me install other releases.
scoop install php will do the magic here.
Again—and I’m going to keep pointing out where Homebrew does things, because I primarily use macOS and Homebrew is fantastic—Scoop uses symlinks for configuration directories. As long as you place your configuration files in the appropriate place, they won’t be overwritten by version changes.
For PHP, you’ll want to make edits only in
~/scoop/apps/php/current/cli. You can either edit php.ini directly or add custom .ini files into conf.d.
In the extensions section of php.ini, you need to explicitly set
The php.ini file will accept Windows-style paths.
Activate the curl, gd, fileinfo, and mbstring extensions. If you’re going to use a database, activate the appropriate extension. Since I’m using Kirby, a flat-file CMS, I haven’t bothered.
php —m at the command line will show you what modules you have installed for CLI PHP.
Save the file, and restart PowerShell. Since we need Composer for Kirby installation and maintenance, run
scoop install composer. To confirm your PHP’s set up correctly, run
composer create-project getkirby/plainkit
in whatever your project directory is. If you need another extension enabled, Composer will error out and let you know in the terminal. Just uncomment the correct extension and try again.
This is the configuration that took some doing. There were a lot of HTML 500 error codes until I managed to zero in on the Apache configuration responsible for pulling configuration in from the custom php.ini files we set up earlier.
scoop install apache. If you’re going to run Apache as a service—which is useful, if you don’t want to keep a terminal window open constantly—then
scoop install sudo as well. The sudo utility acts like the Unix version, elevating privileges for a single command.
sudo httpd -k install -n apache
creates a Windows service named apache, and then you can you can adjust the service with
sudo net start|stop apache
Scoop symlinks Apache configuration into
Open httpd.conf and adjust
DocumentRoot to whatever folder you’re using. Apache won’t accept Windows-style paths, so make sure to use forward slashes and Unix-style pathing.
LoadModules section, activate
mod_vhost. At the bottom of the directives, add the following:
LoadModule php_module c:/Users/[user]/scoop/apps/php/current/php8apache2_4.dll
Note that in PHP 8, there’s no version number in
You need to add
ApplicationType directives, but the crucial discovery is to explicitly set the
PHPIniDir directive to the
current symlink in Scoop.
You’ll want to uncomment the
directive and add VirtualHost information to
extra/vhosts.conf. I use .test domains, so I add the following to
Why is that important?
If you don’t set
PHPIniDir, no matter how many times you restart Apache or adjust php.ini, the server’s never going to pick up those changes.
Testing adjustments to php.ini is as easy as creating a PHP file in your document root. Add
<?php phpinfo(); and load the file in your browser. If you see a blank line for the configuration directory, Apache’s looking in the wrong place for your php.ini.
Caveats and tips
- Don’t adjust php.ini and also create a custom.ini file. Keep your changes in one place.
- Once you’ve gotten things working, add the
~/scoop/persistdirectory to version control.
- Don’t activate extensions you don’t need, either in Apache or PHP.
httpd -twill test your configuration files at the command line. It will also stop parsing at the first error, so expect to use it a lot.
- If the test flag still can’t help you—like the HTTP 500 codes I got despite Apache CLI telling me syntax was fine—check the logs.
- Check, double-check, and triple-check your paths. PHP can use Windows-style, Apache requires Unix-style, and add trailing slashes for directories.