Along with my recent move from Vagrant to Docker I decided to revisit a number of tooling choices that I hadn’t second-guessed in a couple of years. The best new mousetrap I adopted after that review is PhpStorm, an IDE that manages to include a huge amount of features and integration capabilities without feeling bloated.
Here’s how I set it up so far with my Docker/LEMP/WP/JS/Jquery/Bootsteaprap/LESS stack in mind. Though this entry is focused on Windows, PhpStorm is cross-platform and most of what follows applies to Linux and Mac users.wita
1. Third-party Application deSupport/Integration
There’s Docker Support in PhpStorm, though there’s not much support for Docker Compose yet. At least the YAML code style is supported to help you use spaces instead of tabs for indentation in your docker-compose-yml file.
I put tcp://localhost:2375 in the API URL field to get PhpStorm to connect (thanks to this thread), and bingo, a mini-Kitematic interface right within the IDE, with container logs, properties, and bindings.
You can add your Docker Hub credentials: Ctrl+Alt+S to get PhpStorm settings then search “Docker registry”, you’ll then be able to pull images from there. This does not seem to work with the new Docker Store yet.
You can use PowerShell to run PhpStorm’s terminal. First change execution policies like explained here, then put powershell.exe as the shell path under Tools > Terminals in PhpStorm’s settings. Side note: Windows 10 comes with PSReadLine which improves command line editing.
But wait, there’s more better! You can set up Cmder in the same fashion. If you refer to it directly it will fire up a separate window instead of a dockable PhpStorm window, unless you refer to it that way (source):
“cmd.exe” /k “”%CMDER_ROOT%\vendor\init.bat””
Now your terminal is Git aware, has powerful command autocomplete/history capabilities, Ctrl-C/Ctrl-V support, and more, thanks to Clink. Though the Ctrl-R/Ctrl-S history manipulation commands don’t work with cmd.exe, but they do work with Powershell. Now I can’t get Cmder with Powershell to launch within PhpStorm, which sounds like the epitome of a First World Problem. Cmder, you get to live as your own separate window.
Pro-tip: you can hashtag commands you want to re-use, then search these tags back and force with Ctrl-R/Ctrl-S. This persists through sessions too. Again, provided you use PowerShell.
Also, click on BufferHeight mode at the bottom right of Cmder or you won’t be able to scroll back. And notice the convenient search box in that same area.
An alternative to running Cmder within PhpStorm looks somewhat like the reverse, in that you can “attach” PhpStorm from Cmder/ConEmu, which makes the former a tab within the latter. I dabbled with that and found it wonky, your mileage may vary. Again, we’re starting to delve into acute configuritis at this point.
Up/down arrow keys don’t work in bash on Windows. A workaround was added to ConEmu, but Docker for Windows was getting in the way. This was resolved as of Docker 1.12.3, which in combo with Cmder now has bash history, with persistence across sessions.
If your backspace key prints unexpected characters instead of doing what it’s supposed to, bash into your container and type (in my case backspace would issue a Ctrl+H sequence, you might need to edit the string after “erase”):
stty erase ^H
1.3. Node.js and NPM
I’m not one of the cool kids so I’m still using client-side JS/Jquery like it’s 2014 (along with 70+% of the web’s top sites), but I still need Node for Bower and Gulp (package managers to install package managers to install…). PhpStorm got you covered:
Enable NPM in Settings
Here I’m installing the Uglify module with –save-dev, which will update package.json:
1.4. Orchestration Tools, from backend to frontend
We can tie our meta-tools together within PhpStorm, though if you’re using Docker and Windows, you’ll need to work a bit for it.
We just reviewed the Node prerequisite for the best-known package managers and task runners. Meanwhile, to work with PhpStorm, Composer and WP CLI need a PHP engine running either in the host or remotely – a feature which comes with native support for Vagrant but not Docker as of v2016.2 (though that is coming with 2016.3). Install PHP on Windows, or if you really want your remote interpreter, see:
- Dockerize PhpUnit and Force Idea/PhpStorm to Use it!
- Running integration tests in PHPStorm with PHPUnit and Docker
1.4.1. Composer (PHP and WP dependencies)
Here are Composer dependencies, retrievable from Packagist directly in the PhpStorm UI (you can see it recognizes and checks dependencies from my existing composer.json file):
There’s a third-party plugin that adds composer.json autocompletion and inspection, and it now supports custom repositories such as WPackagist. Here again, you’ll need to install a local PHP interpreter, remote ones are not supported despite popular demand. This gives you autocomplete from Packagist as illustrated below.
Incidentally in this screenshot you see WordPress set as a Composer dependency, which is how I currently pull WP and run it in its own directory. I used to have WP as a Git submodule for years, and even briefly tried WP as its own Docker container.
1.4.2. Bower (JS Dependencies)
Installing a package looks very similar to what we’ve seen earlier with NPM. Don’t you love consistency?
Here’s the output of bower list from the integrated terminal:
1.4.3. Gulp/Grunt (Do You Like Infinifactory?)
- See Gulp Task Runner and Using Gulp in WebStorm. I just moved to Gulp from Grunt, both look the same in terms of PhpStorm UI. You need to install it locally instead of globally, though you can install gulp-cli globally (related SO thread).
- Or see Grunt Task Runner and Announcing Grunt support in PhpStorm 8 EAP.
- I don’t use it, but yes there’s also support for Yeoman.
In the screenshot below the JetBrains IDE 1) lets me edit a Gruntfile or Gulpfile, 2) parses it and automatically list the tasks registered in it, 3) lets me point and click to run any of these tasks, 4) show the output in a console. Pretty sweet huh? It is actually a much more functional outcome than the sparse – even cryptic – interaction with Grulp that I’d get through Docker Compose and command line instructions.
Thanks to the underlying NPM support, you get autocomplete for your installed packages when you edit gulpfile.js:
1.4.4. PhpStorm + Gulp + Bower + Composer + Docker, Because You Can
Now, while you can interact independently with Composer, Bower, and Gulp, I try to get the most out of the latter. This means I install/update Composer and Bower dependencies using Gulp with gulp-bower and gulp-composer (who would have thought?).
Windows doesn’t know what to do with .phar files so make sure to create a composer.bat file as per the Composer documentation. Otherwise Gulp-Composer won’t be able to launch Composer, nor will you be able to manually interact with Composer from the command line. You’ll also need to use the bin: setting in your gulp-composer task to point to the path where composer.phar is located.
There is a Gulp-Docker package but it doesn’t parse Compose files, and defining containers in a Gulp task seems redundant. If what you want to accomplish is to make sure your containers are running before you launch Browser-Sync via Gulp (for example):
- Create a bat file with “docker-compose up -d” in it.
- Point to it as an External Tool in PhpStorm
- Edit the Before Launch section of the Run/Debug configuration of your Browser-Sync Gulp task
You could even start Docker for Windows that way. I don’t because I already start Docker when Windows launches.
It’s really on top of Bower that Gulp pipelines will be most useful, as you’ll typically need to:
- Retrieve packages from Bower.
- Sort out exactly which files you’re interested in within these packages. Things such as folder layout and whether there are minified files vary from package to package. There’s also stuff such as readme files that you don’t want in your own project.
- Lint, concatenate, beautify, and add sourcemaps to have centralized CSS and JS files made of your imported libraries + your custom code. These are the files you’ll use for debugging, since they’re legible and code/design can be traced back to its source components.
- Then uglify production-ready versions of these same files (no need for sourcemaps there, unless you want to do some debugging in production).
Behind the scenes, each tool retrieves images from a central public repository, sometimes complemented by private ones:
- Docker -> Docker Hub
- Composer -> Packagist, WPackagist
- Bower -> Bower.io
- Gulp -> NPM
See Libraries.io for module meta-search.
If my screenshots are not enough, watch the following video about Gulp integration. PhpStorm is a super-set of WebStorm so this applies to both:
Since I explained in my Docker for Windows tutorial how to connect to your database container, here’s what it looks like:
Make sure to use the Synchronize command to retrieve the database’s structure and thus enable auto-completion:
For the record, at the end of 2015 JetBrains launched DataGrip – a competitor to the likes of SQLYog or HeidiSQL – but it’s nice to be able to do database work right from the IDE. Database tools in PhpStorm are functionally equivalent to what’s in DataGrip.
1.6. Web Servers
1.7. CSS Preprocessors & Frameworks
PhpStorm comes with native support for SASS, SCSS, and LESS. Myself I use Gulp for that type of task.
1.8. Version Control
There’s also support for SVN though I personally haven’t used it in years.
Use Annotations to get the equivalent of git blame in the left gutter. From there you can see what granular changes amount to, roll them back, or open a separate window dedicated to showing differences between two files (or in this case, two versions of the same file).
1.9. Frameworks & CMS
See WordPress Development using PhpStorm, which covers most needs. The people at JetBrains are pretty thorough and they included support for WP-CLI, but I found plenty of caveats with my Windows/Docker environment.
You can install WP-CLI on Windows using the .phar file and a .bat file just like we did earlier for Composer, or you can install it globally using Composer. In the latter case, you might as well install the psysh console/debugger/REPL. WP-CLI will then use psysh when you type wp shell after bashing into your container (See the Terminal section earlier in this entry). See:
- Interactive PHP Debugging with PsySH
- Advanced WordPress Management With WP-CLI
- Saving Command History within a Container
Note that psysh’s tab completion (for variable names, functions, classes, methods, properties, and files) needs Readline or Libedit in your PHP. The Readline extension is not available on Windows. You could presumably compile your own PHP with libedit support, though that’s a lot of work just for this. Anyway your PHP/WP CLI experience is not going to be optimal, but it sort of works.
Unfortunately, going back to PhpStorm, it relies on a local install and is not aware of my Docker container setup where the database is located. Other people pointed out that remote CLI support would be nice.
Alternatively you can use a Docker image that includes WP-CLI, in which case you’ll have to bash into the container and won’t benefit from auto-complete unless you set that up explicitly (see Tab Completions here).
Finally, here’s a tease screenshot that should get you to keep reading in case you’re not yet using Xdebug:
2. Debugging, Previewing, Testing
2.1. PHP Debugging
2.1.1. Options & Moving Parts
Here’s an outline to wrap our head around the many debugging options:
- PHP interpreter
- No interpreter. See Zero-configuration Web Application Debugging with Xdebug and PhpStorm. This is what I managed to get up and running after some struggle.
- Local interpreter. I tried this but it’s not seeing the database in a Docker container, even though the database is accessible via port forwarding. My head is spinning.
- Remote interpreter. Here’s my epic support thread when I tried to figure it out in 2016.3 EAP. What’s the point of using an interpreter if you don’t need one? In the words of Eugene from JetBrains: “Sometimes people don’t use web servers and prefer to use the CLI mode instead.”
- Run & Debug Starting from the browser
- Run & Debug Starting from the IDE (optionally with Run Configurations)
- PHP Application. Here “PhpStorm fully controls the debugging process: it launches the application, opens the browser, and activates the debugging engine.”
- PHP Script. Here PhpStorm runs a single PHP file locally using a PHP console.
- PHP HTTP Request.
- Built-In Web Server. I don’t see how that could possibly work in combination with Docker.
My first instinct was to use debugging with a remote PHP interpreter. It turns out doing so with PHP running in a Docker container is cutting edge and won’t be officially supported until 2016.3, which is in early access program as I’m writing this. There’s a workaround method for 2016.2 which wouldn’t work for me, so I installed 2016.3 EAP and struggled for days before finally prevailing.
In the end, here’s what worked for me:
- No interpreter, Remote Interpreter, and Local Interpreter all worked once I had sorted out the proper host and mapping. In hindsight it looks trivial, but you wouldn’t imagine the nooks and crannies I went through to sort it out. I haven’t tested this thoroughly, but it feels like Local Interpreter may have a performance edge.
- xdebug.remote_host = 192.168.1.2 (my host’s LAN IP – find yours with ipconfig from the Windows prompt), not 10.0.75.1, not localhost, not 127.0.0.1.
- A single mapping between the local web directory and /var/www/project/web on the server. This is for the Bedrock WP project structure.
If you’re fighting with this, these may help:
- Troubleshooting remote debugging with Xdebug in PhpStorm
- Xdebug and You: Why You Should be Using a Real Debugger
- Xdebug with PHPStorm and a Docker container – You need to set a server name in your web server settings
- Trellis + Xdebug + PhpStorm – I don’t use Trellis but my WP project structure is very similar (see the WP section of my Docker entry), here he’s not including WP itself in his PhpStorm project.
The drawback of PhpStorm’s power and feature wealth is its sprawling option screens. They’re easy to navigate and search, but when you’re talking PHP + Debug + Docker + WordPress, there’s a dozen screens involved, often with overlapping concepts and settings such as mappings and ports.
2.1.2. Scoping What Gets Debugged
If you do stick to your PhpStorm debugging guns, it will come handy to block debugging feedback about code that’s not yours. There are several possibilities:
2.1.3. Too Complicated?
PhpStorm relies on a Chrome extension to receive JS debug information back from the browser. Note that you need to close Chrome DevTools before launching a PhpStorm JS debug session. For details, see my entry on PhpStorm + Browser dev tools.
Here’s a video tutorial:
Here too there’s a quick-and-dirty alternative, with Chrome Logger.
2.3. Browser Auto Refresh with Edit Roundtrips Between IDE and Browser
2.3.1. PhpStorm Live Edit
2.3.2. BrowserSync via Gulp
Alternatively you can use BrowserSync with a task runner (Grunt, Gulp), which is how I personally roll for full-fledged projects. BrowserSync comes with a ghost mode and support for remote debugging with Winre (see this video), the sum of which looks pretty close to the sort of synchronized cross-device mobile testing that Ghostlab offers.
When I make an edit to the LESS file I use to customize/override Bootstrap and save it (Ctrl+S), Gulp catches the update and compiles LESS to CSS, a second or two later my browser shows the update without having to hit refresh. It’s not a full refresh either, only the CSS file is streamed and injected, so the browser doesn’t blink through a blank page. Smooooth.
Add watches on your JS and PHP source files, and never manually refresh your test/dev browser again. Of course in the case of PHP changes there will be a full page refresh.
A note for Docker users: gulp watch processes don’t seem to work with mounted volumes, i.e. file changes don’t get picked up. I tried gulp.watch, gulp-watch, neither would pick up changes, so instead use the files: section of your browserSync task.
2.3.3. Roundtrips with the Browser
If you squint just right, you can not only automatically push changes made in PhpStorm to the browser, but also save changes made in the browser back to your source files. This involves lots of moving parts though, so this section became too long and became its own entry on browser dev tools and addons.
Section to be developed. See:
- Running PHPUnit tests with VVV and PhpStorm
- Running PHPUnit Tests Outside VVV
- PHPStorm Test Workflow
2.5. Code Hygiene & Refactoring
2.5.1. Looking for Duplicate Content
Install PHP Copy/Paste Detector (PHPCPD)‘s phar/bat file the same way we’ve installed Composer and WP-CLI before, then set it up as an external tool with macros (in this context, this means variables) rather than hard-coded paths, so it will work across your projects:
Then Ctrl+Shift A, type “external tools” (or mouse to the Tools menu), select PHPCDP, you’ll get the result in PhpStorm’s Run window:
Section to be developed. See Refactoring Source Code.
3. Other Goodies
This plugin adds a mini RegexBuddy to the IDE.
PhpStorm’s UI always helps you know where you are and navigate around your project easily and quickly. See here the Structure pane listing a linked outline of functions within a longish php page, a visual cue in the margin of the main window showing the function’s span, and a minimap a la Sublime on the right (plugin).
And if you’re looking at the physical layout of your project, both the Project sidebar and top navigation bar (Alt+Home) have a solid feel to them. You’ll like this If you’re the type of person to replace Windows Explorer with Directory Opus or Xplorer2.
3.3. External Tools
We’ve used this as explained above to set up PHPCPD or launch Docker containers. Here’s a more detailed tutorial.
3.4. Interface Automation
PhpStorm has macros, though don’t expect the full power from, say, Microsoft Office VBA. Mouse presses are ignored, the documentation is pretty limited, and if there’s a way to use variables in macros, it’s well hidden. I tried to put the launch of a specific Gulp task into a macro, and all the recorder shows is a generic RunJsbtTask action.
Moreover, you can’t add a macro to a Run Configuration, so the potential for automation from within PhpStorm is limited. I filed a feature request, and I should mention that I found the Jetbrains folks very responsive in my interactions with them.
Don’t be confused by the fact that PhpStorm also use the “macro” word to refer to variables that you can use to customize how you launch External Tools.
3.4.2. Live Templates
The other feature meant to cut time spent typing is Live Templates, i.e. “frequently-used or custom code constructs.” I haven’t used this yet.
3.5. Other Stuff to come
I will keep updating this entry as I dive deeper into PhpStorm’s capabilities, and I feel I’ve only scratched the surface. Eventually I hope to get around to using and properly documenting:
- Linting/code checking LESS/CSS, JS and PHP, using PhpStorm and/or Gulp
- (Unit) testing
- Issue management
You can always check out the plugin directory to find something that works with your own environment.
With my triple screen setup, I can have PhpStorm with all the integrations listed above in (docked or floating) windows, ConEmu, a couple browser windows with dev tools, and a reference book or web page all neatly visible at the same time.
When all of that stuff is up and running:
PhpStorm does a lot, but not everything just yet. Here’s a small list of the things I’ve been looking into that don’t exist:
Using a PHP remote interpreter with a Docker container. Solved with 2016.3 Support for custom Composer repositories. Added with v 1.0.13 of the composer.json plugin.
- Using Composer with a remote PHP interpreter. OK, OK, I’ve installed PHP on Windows since you insist. But this is a bit of a nuisance because Composer will look at the PHP extensions in your local php.ini and may complain that “the requested PHP extension curl is missing from your system.”
- Setting up a CLI with a remote server (in my case for WP-CLI).
- No autocomplete of sources/versions in bower.json
nor package.json, unlike with composer.json (through a 3rd-party plugin). There’s an open feature request. Coming with 2017.1.
- No parsing of docker-compose.yml. They said several times they plan to add that.
- Limited ability to record and trigger macro commands.
5. Summary: Re-Creating a Project From Scratch
5.1. From Boot to Dev
If I need to reinstall a whole project from scratch, it looks roughly like this:
- Pull my project/theme from Bitbucket.
- Launch my Docker containers.
- Import a MySQL dump.
- Copy media assets.
- Launch a few Gulp commands.
- Fully working website running locally and ready to be debugged.
Step 3 can be done via your Docker-compose file (example) or a SQL command.
Step 4 is still a manual process for me, I’ll have to automate/manage that at some point, maybe with a WP plugin and some cloud hosting.
Step 5 should be reduced to a single Gulp master task once Gulp 4 is out of beta (watch Github releases) which will improve task dependencies and executing ordering. Gulp takes care of retrieving PHP libraries (including WordPress and plugins), JS libraries, fonts, CSS, and meshing that with my own code to build an entire production-ready site, while I don’t have to commit any externals in my own source repository.
So I’m not quite pushing a single button just yet to get the whole thing going, but I’d say it’s pretty streamlined and clean.
5.2. Essential Dev Software
And if I were to start on a brand new machine, I’d install and configure the following development suite:
- Docker for Windows
- Git for Windows
- Node, Bower, Gulp, Gulp project dependencies
- PHP, Composer, WP-CLI
- Chrome Canary + extensions
- Firefox Developer Edition + extensions
- SourceTree or GitKraken
From my experience, the worst in the lot is installing NPM dependencies, sometimes it borks for obscure reasons (“unmet dependencies” and similar-sounding bullshit) which may require you to delete node_modules and restart. This can be sloooow.
Sometime in 2017 I plan to build a new PC with Unraid, which would combine native Docker support with Windows as a VM, but at bare metal performance levels thanks to PCI pass-through. Exciting stuff!
6. More resources
- How we use PhpStorm for WordPress Development. Good entry and discussion thread on the cost/benefit of learning the full power locked within this IDE.
- Speed up PhpStorm Right away – Some performance tips.
- JetBrainsTV – Lots of YouTube walkthroughs and tutorials.
- PhpStorm – Top Productivity Hacks and Shortcuts.
- Be Awesome in PHPStorm.
- Keyboard Shortcuts You Cannot Miss. Ctrl-Shift-A works like Launchy or MS Office’s Tell Me. Install the Key Promoter plugin, you can also learn PhpStorm shortcuts at ShortcutFoo.
I’m not going to write a whole post just about this editor, but I do recommend using it when you need more lightweight work done because it’s so fast. I made it my default editor for a variety of file extensions and removed the default Notepad in my shortcuts so they don’t compete in Launchy.
I run PhpStorm and Notepad++ at the same time. using the latter for things such as conf, ini, or log files, or for a quick edit.
A couple pointers: