PHP Elephant by scaldra2 from https://www.flickr.com/photos/7237499@N02/6458472309/sizes/l/. Used under a Creative Commons Attribution-NonCommercial-NoDerivs 2.0 Generic (CC BY-NC-ND 2.0) license.

Hello PHP 7!

With relatively little difficulty, I’m now running PHP 7 alongside PHP 5.6. PHP 7 was released at the beginning of the month, and WordPress was one of the platforms tested against. Given that I can’t stop tinkering with this server’s configuration, I really had no excuse not to set up PHP 7.

Given the myriad services I’m running, I couldn’t switch to PHP 7 outright. While WordPress and YOURLS (powering my url shortener, eth.pw) both support PHP 7, the compatibility list basically ended there.

As I went into this with a fair bit of trepidation (and many backups), what follows is a bit about my experience.

Insights

Support for Redis presented the only complication, as the PECL module I used with PHP 5 isn’t compatible with PHP 7. Fortunately, there’s a PHP 7 branch for the phpredis extension, and that’s working well so far (well enough that you’re reading this, at least). Other than that, passing an appropriate --prefix to ./configure was enough to keep the two versions apart. My init.d script is a derivative of what I had for PHP 5.

Be sure to run ./configure --help first, as I had to enable a few additional extensions/options for my needs.

Build configurations

Purely to demonstrate how I got this done, I’ve included my build configurations for both the main PHP 7 package and phpredis. Fair warning, I probably did something wrong. 😀 I offer no guarantees that this will work, and bear in mind that I did this on a Debian Wheezy box from Linode.

For PHP 7:

./configure --prefix=/usr/local/php7/7.0.0 --with-pdo-pgsql --with-zlib-dir --with-freetype-dir --enable-mbstring --with-libxml-dir=/usr --enable-soap --enable-calendar --with-curl --with-mcrypt --with-zlib --with-gd --with-pgsql --disable-rpath --enable-inline-optimization --with-bz2 --with-zlib --enable-sockets --enable-sysvsem --enable-sysvshm --enable-pcntl --enable-mbregex --enable-exif --enable-bcmath --with-mhash --enable-zip --with-pcre-regex --with-pdo-mysql --with-mysqli --with-mysql-sock=/var/run/mysqld/mysqld.sock --with-jpeg-dir=/usr --with-png-dir=/usr --with-webp-dir --enable-gd-native-ttf --with-openssl --with-fpm-user=www-data --with-fpm-group=www-data --with-libdir=/lib/x86_64-linux-gnu --enable-ftp --with-imap --with-imap-ssl --with-kerberos --with-gettext --with-xmlrpc --with-xsl --enable-opcache --enable-fpm --enable-intl --enable-mysqlnd --with-pear

I know that some of these are redundant, but I tend to be paranoid and prefer as much explicitness as I’m afforded.

For me, the important flags for PHP were --enable-fpm and --enable-mysqlnd. The latter is a bit redundant given the magical combination of other options in that mess above, but since I’m on MySQL 5.6, I wanted to ensure that the native driver was chosen.

For phpredis:

./configure --prefix=/usr/local/php7/phpredis --with-php-config=/usr/local/php7/7.0.0/bin/php-config --enable-redis

PHP configurations

My php-fpm.conf and php-fpm.d/*.conf files are slightly modified versions of what ships with the distribution. I added the following to my php.ini.

php.ini

max_execution_time=30
memory_limit=128M
error_reporting=0
display_errors=0
log_errors=0
user_ini.filename=
realpath_cache_size=2M
cgi.check_shebang_line=0
zend_extension=opcache.so
opcache.enable_cli=1
opcache.save_comments=1
opcache.fast_shutdown=1
opcache.validate_timestamps=1
opcache.revalidate_freq=60
opcache.revalidate_path=1
opcache.use_cwd=1
opcache.max_accelerated_files=100000
opcache.max_wasted_percentage=5
opcache.memory_consumption=64
opcache.consistency_checks=0
extension=redis.so

Errata

To make it easy to build the next release without losing my configurations, I kept all of my files in /etc/php7 and symlinked them to where PHP 7 expected them to be: /usr/local/php7/7.0.0/etc and /usr/local/php7/7.0.0/lib/php.ini. Similarly, I added some symlinks in /usr/bin to make it easier to access PHP 7 via CLI.

When the next version is released, I’ll build it with a new prefix, alongside the existing version. I’ll then symlink the “base” directory I created with version 7.0.0 to the directory for the new release, limiting how many things I need to change with each release. This is, at least, until all of my PHP applications support PHP 7.

Other resources

  • PHP 7 on Debian Jessie – intended for a version before mine, this was helpful for general direction
  • phpredis with PHP 7 – helpful for understanding how I could add Redis support to PHP 7, before I panicked