Recently PHP 5.5 got EOL’d, but PHP 5.6 will be supported for another two years. On Debian, this is a just a matter of upgrading the php5 package, but FreeBSD splits it out into two packages: php55 and php56, not to mention that extensions are also split out this way. The fact that I’ve installed php via ports also complicates things.

Doing the deed

This assumes portmaster is installed.

Listing the installed php55 packages:

$ pkg info | grep php55
php55-5.5.38                   PHP Scripting Language
php55-ctype-5.5.38             The ctype shared extension for php

Get the original ports path they were installed from (pkg query is a fantastic command to have in your toolbelt), and convert any 5.5 refereces to 5.6:

$ pkg query "%o" $(pkg info | grep php55 | cut -f 1 -d ' ' | tr '\n' ' ') \
  | sed 's/55/56/g'

For the sake of brevity, I’m going to place the list of packages into a temporary file

pkg query "%o" $(pkg info | grep php55 | cut -f 1 -d ' ' | tr '\n' ' ') \
  | sed 's/55/56/g' > /tmp/php56-packages.txt

I’m pretty sure that all the packages I care about have 5.6 equivalents, but just to be sure, let’s check that those directories exist in the ports directory:

while read d; do [[ -d /usr/local/"$d" ]] && echo "$d does not exist"; done < /tmp/php56-packages.txt

Copy over the ports' options directory. (skip this step if you think any packages may need to be compiled differently):

mkdir -p /var/db/ports/lang_php56/ /var/db/ports/lang_php56-extensions/
cp /var/db/ports/lang_php55/options /var/db/ports/lang_php56/
cp /var/db/ports/lang_php55-extensions/options /var/db/ports/lang_php56-extensions/

Now begins the actual changes! Build 5.6 over 5.5 with portmaster:

sudo portmaster -n -o /usr/ports/lang/php56 lang/php55

Do a quick dry run with portmaster (if there are any new options that can be set, portmaster will open up a prompt):

portmaster -n $(cat /tmp/php56-packages.txt | tr '\n' ' ')

Install the other packages sequentially, in the same manner as the main php56 package:

cat /tmp/php56-packages.txt | grep -v 'lang/php56$' | \
  while read p; do echo portmaster -D --no-confirm -o "/usr/ports/$p" "$(echo "$p" | sed 's/56/55/g')"; done

Restart any necessary daemons, and you’re done! This was a learning process for me, I’m sure this could be compressed into a nice script. Of course, if you need to upgrade many machines, or downtime is an issue, building packages from the ports system (possible with portmaster’s -g flag), and then installing them wholesale would cut down on the amount of time spent compiling everything.