After twenty-two years as a Mac user, I switched to Windows 10. I was motivated by excellent hardware that became available (the Dell XPS 15 specifically). Macbook Pros had remained stagnant for years and I wanted a larger, better screen. I do a lot of photography, so 4k and the Adobe RGB colorspace were quite compelling!

While I was excited for the hardware, I was nervous about the OS. I had played with Windows in the past and was always underwhelmed. I was scared my web development productivity would plummet, and I dreaded losing important software. It turns out I was wrong. My web development workflow on Windows 10 is as productive as it was on OS X, and I continue enjoying the same software to develop PHP on Windows.

I tell this story to my fellow PHP developers, and they look at me like I’m crazy. Just a few years ago I would have agreed with them—maybe even a few months ago! However, I must commend Microsoft for its progress on Windows 10. I find Windows 10’s aesthetics simple and well-designed. Windows 10 is stable with the “Threshold 2” update. And my new Dell XPS 15 Core i7 Skylake laptop is powerful and packed with pixels. I am happy with Windows 10. Perhaps most interestingly, based on my own experience, the difference between OS X and Windows continues to shrink. Both borrow good ideas from one another, and more and more software is cross-platform or web-based.

This post covers what I learned during the transition from OS X to Windows 10 that is relevant to PHP developers. It turns out there isn’t much to relearn, and you don’t even lose the command line!

My Software Runs on Windows

It is paramount that my PHP development software runs on Windows. I also want the transition from OS X to Windows 10 to be seamless. I am happy to report that all of my PHP development software does, in fact, run on Windows 10, including:

This list should be familiar because it is the same software I used to develop PHP on OS X.

First a Note: It’s a Best Practice to Virtualize

It’s important to emphasize that I heavily rely on Vagrant virtual machines to preview my local applications through an environment that matches their production servers. I would do this even if I developed in Linux. A development machine is never going to exactly match a production machine the same way a scripted Virtual Machine can. It is silly to not virtualize production environments regardless of your local OS. Windows, OS X, and even Linux users should all use a virtual machine to preview local applications and avoid software discrepancies with production servers.

So when evaluating a development OS, the only consideration is the development experience. This post demonstrates that Windows 10 is finally a capable platform for PHP development. Whether you are building custom applications or contributing to your favorite open source projects, Windows 10 is finally a sane choice as a modern PHP development platform. What follows is a collection of what I’ve installed to get going on my Windows development machine.

PHP 7.0 Runs on Windows

The PHP internals team provides pre-compiled PHP binaries for Windows. These binaries are available to download at http://windows.php.net/download/ for both 32-bit and 64-bit operating systems. I use the 64-bit (non-thread-safe) PHP 7.0 build for Windows 10.

The thread-safe builds are intended for PHP developers running a local Apache web server. The non-thread-safe builds are intended for PHP developers running a local IIS web server. I do not run Apache or IIS. Instead, I use PHP’s built-in web server or a Vagrant virtual machine when developing applications on my own computer.

It is important to download and install the Visual C++ Redistributable that complements the selected PHP binary. I use the x64 VC14 C++ Redistributable required by the PHP 7.0 binary.

The PHP pre-compiled binary is a ZIP archive. I extract it to C:\Users\josh\Apps\php7.0\ on my computer, and I add that directory to the system PATH environment variable.

I recommend the following changes to the php.ini file located immediately beneath the PHP install directory.

First, I uncomment the extension_dir directive. The resulting line reads:

extension_dir = “ext”

Next, I locate the section named “Dynamic Extensions” and uncomment most of the included PHP extensions. My php.ini file uses these dynamic extensions:

extension=php_bz2.dll extension=php_curl.dll extension=php_fileinfo.dll extension=php_gd2.dll extension=php_intl.dll extension=php_mbstring.dll extension=php_exif.dll extension=php_openssl.dll extension=php_pdo_mysql.dll extension=php_pdo_sqlite.dll

Xdebug Runs on Windows

Derick Rethans provides a pre-compiled Xdebug binary for Windows at http://xdebug.org/download.php. I move the downloaded .dll PHP extension into the C:\Users\josh\Apps\php7.0\ext\ directory, and I append this text to my php.ini file:

[xdebug] zend_extension = php_xdebug-2.4.0rc2-7.0-vc14-nts-x86_64.dll xdebug.default_enable = 1 xdebug.scream = 1 xdebug.coverage_enable = 1 xdebug.profiler_enable = 0 xdebug.profiler_enable_trigger = 1 xdebug.profiler_output_dir = "C:\Users\josh\Apps\php7.0\profiles" xdebug.remote_enable = 1 xdebug.remote_host=127.0.0.1 xdebug.remote_port = 9000

The zend_extension value must be the exact filename of the .dll file. This name may vary depending on the specific Xdebug build.

The second line, xdebug.default_enable , activates Xdebug by default.

The xdebug.scream directive instructs Xdebug to ignore the @ suppression operator.

The xdebug.coverage_enable directive activates Xdebug’s code coverage feature that often complements PHPUnit tests.

The xdebug.profiler_enable directive disables Xdebug’s profiler feature by default since it consumes a lot of system resources and disk space on every PHP run.

The xdebug.profiler_enable_trigger directive, however, lets me selectively activate Xdebug’s profiler by passing the ?XDEBUG_PROFILE=1 query parameter to a PHP script.

The xdebug.profiler_output_dir is the path to a directory in which Xdebug stores profiler output data. Profiler data can consume a lot of disk space.

The xdebug.remote_enable directive activates Xdebug’s remote debugging features.

The xdebug.remote_host and xdebug.remote_port directives tell Xdebug the host and port to which Xdebug sends debugger information. The PHPStorm IDE listens on 127.0.0.1:9000 for inbound Xdebug debugger information.

PHPStorm Runs on Windows

I use PHPStorm with PHP 7.0 and Xdebug. PHPStorm is a popular integrated development environment (IDE). It is commercial software availble via subscription at https://www.jetbrains.com/phpstorm/.

I never appreciated PHPStorm until I did most menial development tasks by hand. Only then did I learn to love PHPStorm. There is comfort and simplicity in its perceptually complex user interface. I won’t go into the details; PHPStorm’s features are listed on its website. I do, however, appreciate PHPStorm’s support for PHPUnit, Xdebug profiling, Xdebug code coverage, Composer, and PHP Code-Sniffer.

To configure a new PHP 7.0 interpreter in PHPStorm, I open PHPStorm's settings window (Ctrl+Alt+s) and navigate to Languages & Frameworks > PHP and click the … button located to the right of the Interpreter dropdown.

In the subsequent window, I click the … button to the right of the PHP executable text field and select the C:\Users\josh\Apps\php7.0\php.exe executable file beneath the PHP install directory. PHPStorm automatically finds and reads the php.ini file. PHPStorm also recognizes the Xdebug extension.

Finally, I navigate to Languages & Frameworks > PHP > Debug to ensure the Xdebug Can accept external connections checkbox is checked and the Debug port value is 9000. These settings tell PHPStorm to listen for inbound Xdebug debugger data on 127.0.0.1:9000 .

Composer Runs on Windows

Composer is a PHP dependency manager that is often attributed as the catalyst for the modern PHP renaissance. Composer changed how I develop PHP applications. It’s an invaluable tool that I use everyday.

Composer provides a native Windows installer on its website at https://getcomposer.org/download/. The installer puts the Composer binary in the C:\ProgramData\ComposerSetup\bin\ directory, and it puts global vendor packages into the C:\Users\josh\AppData\Roaming\Composer\vendor\bin\ directory.

After I add the C:\Users\josh\AppData\Roaming\Composer\vendor\bin\ directory to my system PATH environment variable, I can invoke any Composer-managed global binary in the command prompt.

PHPUnit Runs on Windows

PHPUnit runs on Windows, and it can be installed with Composer. I install PHPUnit with this command in the Windows command prompt:

composer require global phpunit/phpunit

When Composer completes its installation, I can invoke PHPUnit on the command prompt:

phpunit

In PHPStorm, I specify the path to the PHPUnit executable in the settings panel (Ctrl+Alt+s). I navigate to Languages & Frameworks > PHP > PHPUnit. I click the Path to phpunit.phar radio button and enter the C:\Users\josh\AppData\Roaming\Composer\vendor\bin\phpunit PHAR archive path in the Path to phpunit.phar text field.

PHP Code Sniffer Runs on Windows

PHP Code Sniffer provides code linting against the PSR-1 and PSR-2 code styles (among other features). PHPStorm uses PHP Code Sniffer to lint code in real-time with inline notifications of syntax and style mistakes.

I install PHP Code Sniffer with Composer.

composer require global squizlabs/php_codesniffer

When Composer completes its installation, I can invoke the phpcs binary on the command prompt:

phpcs --help

In PHPStorm, I specify the path to the PHP Code Sniffer executable in the settings panel (Ctrl+Alt+s). In navigate to Languages & Frameworks > PHP > Code Sniffer. I click the ... button and, in the subsequent dialog, select the C:\Users\josh\AppData\Roaming\Composer\vendor\bin\phpcs.bat file for the PHP Code Sniffer (phpcs) path text field.

PHP Mess Detector Runs on Windows

PHP Mess Detector detects messy PHP code, including “unused variables, bugs, suboptimal code, or overcomplicated expressions” according to its website. PHPStorm uses PHP Mess Detector to lint code in real-time with inline notifications.

I install PHP Mess Detector with Composer.

composer require global phpmd/phpmd

When Composer completes its installation, I can invoke the phpmd binary on the command prompt:

phpmd --help

In PHPStorm, I specify the path to the PHP Mess Detector executable in the settings panel (Ctrl+Alt+s). I navigate to Languages & Frameworks > PHP > Mess Detector. I click the … button to the right of the Configuration dropdown and, in the subsequent dialog, select the C:\Users\josh\AppData\Roaming\Composer\vendor\bin\phpmd.bat file in the PHP Mess Detector (phpmd) path text field.

Git, Bash, and SSH Run on Windows

I admit that I miss a familiar bash shell and an underlying BSD subsystem. However, Git Bash is a competent bash substitute on Windows. Git Bash is a psuedo-bash shell on Windows that provides oft-used bash commands and transparently maps them to their DOS counterparts.

Git Bash, as its name suggests, also provides the Git version control system complemented by a built-in SSH client that operates exactly like it’s Unix-y brethren. The SSH client uses ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub private and public SSH keys, and it uses a ~/.ssh/config file for SSH connection aliases.

Git Bash is available for download at https://git-scm.com/downloads.

Out of the box, Git Bash runs slower than I prefer because it customizes the command prompt color based on the current Git repository branch. This overhead slows Git Bash’s response time. Git Bash is fast again when I remove this line from the etc\profile.d\git-prompt.sh file beneath the Git Bash install directory:

PS1="$PS1"'`__git_ps1`'

As you can see in the screenshots above, I run Git Bash via Cmder, a Windows user interface that wraps nicely around Git Bash, the native Command Prompt, or PowerShell.

Windows, PHP, and Me

Many of my friends who use OS X and Linux carry negative preconceptions of Windows, especially with regards to PHP development. These were true. I recently switched to Windows 10 after twenty-two years with a Mac, and I believe these negative preconceptions of Windows are now false.

All of my software runs on Windows. I write PHP with a stellar IDE using the latest and greatest features available in PHP 7.0.

I also run Xdebug, the de facto PHP debugger and code profiler, to analyze and optimize my PHP code. I step-debug my code in PHPStorm when I run into otherwise tricky-to-diagnose issues with my PHP code.

I write PHPUnit tests and generate real-time code coverage statistics so I know which code is tested and which is not.

I use PHP Code Sniffer and PHP Mess Detector to ensure my code is efficient and adheres to PSR-1 and PSR-2 code styles.

I run all of these tools in a familiar bash-like terminal with Git and SSH not unlike my previous OS X development environment.

Yes, I was hesitant moving to Windows. My time developing PHP on Windows 10, however, is efficient, familiar, and productive. Windows 10 supports the tools I need to create and deploy modern PHP applications.