A PHP Version Switcher for the AMP stack on OS X

A friend is thinking about buying MAMP Pro so he can test on different versions of PHP. Since I just set up version-switching myself, for free, here’s how I did it. Hopefully it’ll save someone a bit of money or frustration.

This is happening on a Mac, with the latest version of OS X, (Currently 10.11.3 El Capitan), using the pre-installed version of Apache, and Homebrew as a package manager.

Step 1: Install more than one version of PHP on your system

Using Homebrew you can install a version of PHP, then “unlink” it so it’s not currently being used:


brew install php7
brew unlink php7

If you want to be able to switch PHP versions on the command-line there’s a tool called PHP Version that does the heavy lifting for you, and with Homebrew it’s easy to install.

Step 2: Make it easy to change the PHP version Apache is using

First, stop the main Apache config, (/etc/apache2/httpd.conf), file from loading PHP. Find any line that mentions PHP modules and comment it out, (put a # at the beginning of the line). For example:


#LoadModule php5_module libexec/apache2/libphp5.so
#LoadModule php5_module /usr/local/opt/php56/libexec/apache2/libphp5.so

Now we need an Apache config file for each PHP version that you want to run. I’ve put these files in /etc/apache2/other/ and used the file extension “.conffile” to prevent Apache from auto-loading them:

A screenshot of /etc/apache2/conf/other

Each of your .conffile files needs to have the location of the PHP library, and any extra PHP info. This is the contents of my php-7.conffile:


LoadModule php7_module /usr/local/opt/php70/libexec/apache2/libphp7.so
<IfModule php7_module>
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps
<IfModule dir_module>
DirectoryIndex index.html index.php
</IfModule>
</IfModule>

is very similar, but has the path of the PHP 5 .so file and the IfModule conditional checks for php5_module.

If you have any existing php*.conf files in /etc/apache2/other/ they can be blank.

Next we need to make an easy way to tell Apache to use one of the .conffiles, which I’ve  done by creating a symbolic link to the one I want to use. Since I don’t like typing out ln commands I’ve created a script, which I call php-v.sh.

#!/bin/bash
if [ $1 = 7 ]; then
PHP_VERSION=7
else
PHP_VERSION=5
fi
`sudo ln -Fs /etc/apache2/other/php-$PHP_VERSION.conffile /etc/apache2/other/php.conf`
`sudo apachectl graceful`
echo "PHP version switched to $PHP_VERSION"

This script symlinks /etc/apache2/other/php.conf to the .conffile that I want to use, (using the -F switch to overwrite the old symlink), and restarts Apache. It needs sudo so it’ll ask for your password.

Finally, it’s nice to have php-v.sh available from everywhere, so I’ve created a symlink from ~/bin/php-v, which is in my PATH, to the actual script:


ln -s /Users/John/Developer/Scripts/php-v.sh /Users/John/bin/php-v

And now I can switch PHP versions at will:A screenshot of my terminal, having just switched PHP versions quickly & easily!

Show the OmniFocus Tasks You Did Today on your Desktop

This morning Ken Case retweeted this:

Using Automator, not TextExpander

I’ve wanted a solution to show me what I accomplished in a day for a while, but I don’t use TextExpander. Luckily Colter Reed’s script to log today’s completed OmniFocus tasks is Javascript for Automation, which can be run with the built-in OSX app, Automator, so I built an Automator workflow that runs the script, (I just pasted Colter Reed’s script into an Automator “Run Javascript” action, then made one tweak when I ran into a small problem). If you’ve never used Automator before don’t worry – I hadn’t either! Here’s my Automator workflow file, (it’ll need to be unzipped). It returns a bunch of text, which we’ll deal with next.

Put the Results on your Desktop with GeekTool

GeekTool can take text from a shell script and display it on your desktop, and you can set it to refresh that text however often you want. I created a new shell Geeklet with GeekTool with the following script:

Automator Runner ~/Developer/Scripts/omnifocus-completed.workflow | sed -e 's/^"//' -e 's/"$//' -e 's/\\"/"/g'

For some reason the Automator Runner returns the text with quotation marks around it, so the parts after the pipe remove the quotation marks, (using instructions from Stackoverflow).

When choosing your refresh interval keep in mind that the script grabs focus from OmniFocus when it runs, which will be annoying if you are working in OmniFocus and you have a short refresh interval. I also don’t know how much battery this will eat for those of us on laptops.

With some font & colour tweaking, my desktop now looks like this:

omnifocus-completed-desktop-screensho

Update (October 9, 2015): This morning a bunch of tasks I did last night, but before midnight, were still on my desktop, so I went debugging. It looks like OmniFocus, (at least my version, which is a pre-release test version), is exposing the completedDate value to Javascript as a UTC date/time, but with a Timezone offset set, so things done in the evening might remain on the list of “today’s” completed tasks, (this might reverse on the other side of the world, with things you do in the morning not appearing). To fix this I’ve modified the startOfDay() function to take the Timezone Offset into account. I assume this is a bug and will be temporary, so I’m not updating the downloadable Automator action above. Here’s the updated startOfDay() function:


function startOfDay() {
// The day started at midnight this morning
var d = new Date(),
hours = 0,
minutes = 0;

if( d.getTimezoneOffset() !== 0 ) {
    hours = Math.round( d.getTimezoneOffset() / 60 );
    minutes = d.getTimezoneOffset() % 60;
}

d.setHours( hours );
d.setMinutes( minutes );
d.setSeconds( 0 );

return d;

}

Update (November 3, 2015): I used quotation marks in a task name, and they came out escaped on my desktop. I’ve updated the command line for the geeklet to strip the slashes from before double quotation marks;

Vanilla Speed

Me: I wonder how to make this cool new HTML5 feature interact with Javascript properly.

Googles…

Stack Overflow Answer #1: Use this great jQuery function!

Stack Overflow Answer #2: Underscore.js is better, us it! You only need 1/2 a character of code.

Smacks desk in frustration.

I’m working on a major overhaul of an existing website that focuses on speed and a great mobile experience that has never used Javascript libraries, (it was originally written in 2007 before they were a thing), and we’re not changing that. For this website a library is a bunch of extra code to download, execute, and take up memory, which adds extra function calls between the code I write and the things that happen in the browser – more CPU cycles, more battery drain, more waiting, and no benefit to our users and customers.

If we were using jQuery I wouldn’t have spent some time looking up the differences in event creation between browsers, and I might not have spent the morning figuring out why a datalist wasn’t appearing properly in Firefox, or maybe I would have had to do that bit of debugging anyway. One thing that doesn’t help me move the project along at all is other people’s over-reliance on Javascript libraries that is so prevalent. In 2007 when I had a problem I could Google it, or post to a forum, and find an answer, (assuming it had been done before), today I experience the sequence of events at the top of this post several times every day. This is why the trio of blog posts last week, (Marco Arment’s post about PPK’s post about John Gruber’s take on Facebook Instant), have really resonated with me. PPK is right, we need to stop relying on libraries, whether it’s jQuery, underscore, or whatever. There are times when a library is the right tool, but with modern Javascript APIs, HTML5, and CSS3, and good browser support for all but the absolute bleeding-edge.

To use a Javascript library is to externalize the cost of development onto your customers and users.

Despite my frustration with the “use some library” responses on Stack Overflow questions using plain vanilla JavaScript has turned out to be an enjoyable learning experience. I’ve been able to make everything work, (so far), with way less code than was needed in 2007. Of course, if your browser can’t handle the project’s Javascript requirements the JS is not loaded at all and you get the plain HTML experience, which isn’t so bad either.

For more on choosing not to burden your users and customers with unneeded slowness, see the ALA article Choosing Vanilla Javascript, which is 15 months old now, and things have just gotten better since it was published!

PhpStorm Review

Late last year I kept hearing a lot about PhpStorm 8, especially from WordPress people and wanted to try it out but the price was stopping me, (it turns out the price is probably worth paying – but it’s hard to know if the price is worth paying until you’ve already paid the price). Luckily for me WP e-Commerce has some licenses for core contributors, and apparently I count, (JetBrains, the people who make PhpStorm, provide licenses to open-source projects at no charge – thanks!).

One of the things that JetBrains asked in return for the licenses was that we try to write reviews of our experience, and after many months of using PhpStorm, here are my thoughts.

PhpStorm crashed several times in the 24 hours after I installed it, not a good start. Support suggested installing the EAP version, which is like a beta stream, which fixed the problem. Since then I’ve switched back & forth between the current release and EAP versions of PhpStorm, but I usually use the EAP, because I like shiny things.

Performance

I had heard that PhpStorm was fast, but it’s a Java app, (like Netbeans or Eclipse), so I had my doubts. When first installed there were some pretty big performance issues, especially related to scrolling. PhpStorm was exhibiting what I refer to as “that Java scroll lag” – one of the reasons I tend to avoid Java apps. There was also a problem that when scrolling with the mouse the text would disappear, which makes mouse scrolling nearly useless. Eventually I learned that there’s a version of PhpStorm for OS X that comes with a bundled, tweaked, Java Run-time Environment, and using that version of PhpStorm solved these problems.

When comparing PhpStorm’s performance to Sublime Text, (2 or 3), Sublime Text is still way faster. PhpStorm feels like a normal app, but ST3 has that amazing snappiness that Sublime Text users have come to love, and want to see everywhere. While PhpStorm’s performance is satisfactory, it’s not as blazing fast as the chatter led me to believe, but the combination of decent speed, and the other benefits that of using a real IDE, mean it helps me write cleaner code faster.

Setup

Like most coding programs, especially Java ones, PhpStorm hurt my eyes out of the box, but the look is tweakable enough to make it look how I want. There are two built-in themes, (“Default” and “Darcula”), and you can load 3rd-party colour schemes for the text editor. I think it might be possible to load 3rd-party themes as well but I haven’t investigated this. Switching to the Darcula theme, and switching to the Predawn colour scheme, (I can’t remember where I found the PhpStorm port, maybe it even came with it), and Inconsolata made PhpStorm feel like home.

Coming from ST3 I re-mapped some keyboard shortcuts to match ST3 make the transition easier and make it easier to switch between the two when needed.

I had to download extra drivers to connect to MySQL, which was kind of annoying, but I suspect might be license-related.

And Java. PhpStorm 8 requires Java 6, which is no longer installed on Macs because it’s so old, that’s why there’s a version offered for OS X with a bundled JRE. It’s possible to install Java 6 with a package from Apple, because we all love having several versions of Java installed, or it’s possible to tweak some plist files to let PhpStorm run with Java 8, (the current version). Fortunately, it looks like PhpStorm 9, (which I’m running the EAP of now), will do away with this requirement.

Code Inspection

This is an IDE, so it’s aware of any databases that get used. This is great most of the time, (the code inspector tells you if you mis-type a column name, for example), but the it also fusses when I build big SQL queries by concatenating strings. So far I’ve just ignored these complaints.

If I include a file like this in WP: include( get_stylesheet_directory() . ‘/myfile.php’); PhpStorm thinks that myfile.php doesn’t exist, even if it does. Since this is the “right way” to include files in WP themes, and PhpStorm advertises built-in WP knowledge, PhpStorm should understand it.

When making a commit to your preferred Source-Control system, (Git, right?), PhpStorm inspects the code you’re committing, and if there are errors or warnings it pops up a window saying so, and gives you a chance to fix these problems. This is a great way to slowly clean up the code of older projects with lots of legacy, (read: “written before I knew better”), code. However, it’s also kind of annoying when unfixable errors or warnings are included, like when I’ve concatenated together an SQL query.

I was working on a plugin that works with WooCommerce and PhpStorm complained that I was assigning the return value of a function that returns void to a variable. It turns out that WooCommerce has several PHP DocBlocks that state a function returns void when it actually returns a value. Thanks to a WP e-Commerce copy of PhpStorm for pointing out errors in WooCommerce!

Annoyances

If someone from Jetbrains reads this, consider these bug reports!

text-gone-bonkers

Sometimes the fonts go bonkers. When I was first setting PhpStorm to use Inconsolata they did, (that was using the release version), and a few times on the EAP I committed some code, and when the commit finished the display went crazy again.

PHPStorm Power Consumption

Power consumption – I’m not sure how it compares to Sublime Text, but it’s consuming more power than Photoshop today – #2 on the list behind Safari with 11 tabs open.

 

The first time I used the “Pull Up” refactor tool, which lets you pull methods up from a class into the parent class, I pulled up a bunch of static methods. PhpStorm didn’t actually go and find the places where the methods were called and change the calls, which I thought was the point of the “smart” IDE. Inheritance would mean that these methods would still be available, but there’s no reason to load the child class if everything I need is in the parent.

The auto-complete can be really bizarre. Often doesn’t pick the logical thing, or even the first thing in the suggestion list. For example, if I type “col” then press tab or enter autocomplete completes as “columns” not “color,” even though color is the first suggestion. It even insists on completing as “columns” if I type “colo” and press tab/enter. This drives me mad.

Search for any file, (I’ve got it mapped to Cmd+P to match Sublime Text): If a project has several files with the same name there doesn’t seem to be mapping that makes sense. To me it would make sense for the first option to be the one I used the most recently, or the one “closest” to whatever file I’m already looking at in the directory structure. If the files are sorted at the moment, it looks like it’s alphabetical, which should change.

Auto-change formatting: I try to use WordPress style in most of my PHP & Javascript – especially for WordPress-related work! WP style suggests putting a space around function parameters in both Javascript and PHP. However, if I’m doing chained calls in Javascript PhpStorm removes the space after the last function argument when I press the . key. For example:


$( 'body' )
// becomes
$( 'body').
// as soon as the period is typed

When PhpStorm 8.0.3 came out I started getting SSL error messages on startup. Apparently there’s a problem in some SSL-related part of the bundled JRE. 8.0.3 came out on February 13 and there’s still no fix. The current EAP doesn’t have this problem.

PhpStorm’s licensing scheme for open-source projects has changed this year, so I need a Jetbrains account, the licence is issued from WP e-Commerce to that account, then I’m supposed to sign in to the account with PhpStorm and it’ll activate. Unfortunately the SSL bug prevents PhpStorm from talking to the Jetbrains servers, so I can’t activate my PhpStorm license. Luckily the EAP comes with its own license, otherwise I would be out of luck. A bug that prevents customers from activating software is a very big bug.

Conclusion

PhpStorm is good, very good at some things, especially the IDE-type functionality I was looking for. Integrated code inspections & linting were a welcome surprise that is really helping my code look better and encouraging me to write better in-line documentation. There have been problems, though, that might have caused me to abandon PhpStorm I hadn’t pre-decided to give it a real chance. I nearly always use the EAP both because I like shiny things, and because the bugs in the release version of the software are annoying, or serious, enough to drive me into the arms of the EAP.

So, is PhpStorm worth the purchase price? Probably. It handles code completion, data-source awareness, most refactoring, and all its IDE-related functionality quickly and as promised, (or very nearly so). The problems tend to be in other areas, and from the state of the current PhpStorm 9 EAP, most of these problems will be solved soon.

Xdebug is not friends with WordPress + create_function()

If you use Xdebug for debugging WordPress-based sites there’s something you should be aware of. If function created with PHP’s create_function() are hooked to WordPress actions or filters, any time $wp_filters is in the scope Xdebug sends invalid XML to the Xdebug client, (like your IDE). If the Xdebug client doesn’t deal with the invalid characters before attempting to parse the XML it will fail. IDEs deal with the parsing failure in different ways, SublimeTextXdebug doesn’t show the call stack or list of current variables but doesn’t crash entirely so debugging can continue. I don’t know how other IDEs handle the failure.

Why the XML is Invalid

create_function() makes a new function, gives it a random name that starts with a null character, and returns that function name as a string. When that string is passed to WordPress’s add_filter() or add_action() functions the name that create_function() returned is used as an array key in deep within the $wp_filters global. When Xdebug sends the list of variables back to an Xdebug client it is sent as XML and the null character encoded as &#0; which is illegal in XML.

How to solve the Problem

Ideally Xdebug would only send valid XML to the Xdebug client, but the bug report has been open for a year and doesn’t seem to be high priority so developers should solve the problem by avoiding create_function()

Avoiding create_function() is Good Coding

create_function() eval()‘s the code that’s passed as the second argument, and eval() is something to be avoided, so create_function() is too. This Xdebug bug makes us avoid create_function() for actions and filters in order to keep Xdebug useful, with the side effect of making our code a bit more secure.