PHP7, how to migrate your application

Colomb Thomas
Oct 5, 2016 · 3 min read

Following my first story on PHP7 deployment at Dailymotion, in this story I will explain to you how find backward incompatibilities in your codebase to prepare your website for PHP7.


phpcs & phpcompatibility reporting

PHPCS code sniffer that that tokenizes PHP, JavaScript and CSS files to detect violations of a defined coding standard. We’ll use this tool with PHPCompatibility which is a set of sniffs that allow you to analyse your code for compatibility with newest PHP version.

installation :

# create working directory
mkdir ~/php7-tools/
cd ~/php7-tools/
# clone repository phpcs
git clone git@github.com:squizlabs/PHP_CodeSniffer.git phpcs
# install phpcompatibility code sniffer
cd phpcs/CodeSniffer/Standards/
git clone git@github.com:wimg/PHPCompatibility.git PHPCompatibility
# you are ready !

usage :

for f in $(find . -name "*.php"); do ~/php7-tools/phpcs/scripts/phpcs -n --standard=PHPCompatibility $f; done

this command line will scan every php file in your codebase, and will output php 7 incompatibility issues. I scan each file individually with a for because sometimes phpcs has problems with very big files and memory limit is exceeded.

output example :

FILE: ...file.php
--------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
--------------------------------------------------------------------
284 | ERROR | preg_replace() - /e modifier is forbidden since PHP
| | 7.0
--------------------------------------------------------------------
Time: 51ms; Memory: 8MbFILE: ...file2.php
--------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
--------------------------------------------------------------------
96 | ERROR | Use of deprecated PHP4 style class constructor is not
| | supported since PHP 7
--------------------------------------------------------------------
Time: 66ms; Memory: 8Mb
FILE: ...file3.php
--------------------------------------------------------------------
FOUND 2 ERRORS AFFECTING 2 LINES
--------------------------------------------------------------------
145 | ERROR | 'string' is a reserved keyword introduced in PHP
| | version 7.0 and cannot be invoked as a function
| | (T_STRING)
--------------------------------------------------------------------

Github links : PHPCS, PHPCompatibility

PHAN static analysis :

Phan is a static analyzer that looks for common issues and will verify type compatibility on various operations, it also can report php 7 backward incompatibilities of your codebase.

installation :

This tool must be installed php 7 with an additional extension, php-ast.

# php7 installation (ubuntu)
apt-get install software-properties-common
add-apt-repository ppa:ondrej/php
apt-get install php7.0-cli php7.0-common php-ast
# create working directory
mkdir ~/php7-tools/
cd ~/php7-tools/
# clone phan and install phan
git clone git@github.com:etsy/phan.git
cd ~/php7-tools/phan
composer install
# get all php files in your codebase
cd /your/directory/
find . -name "*.php" > phanlist.txt
# launch analysis
~/php7-tools/phan/phan --progress-bar -i -b -f phanlist.txt -o analysis.txt

At the end of the analysis, you will have a big txt file with all problems.

output :

# get sorted top of errors
cat analysis.txt| cut -d ' ' -f2 | sort | uniq -c | sort -n -r
1407 PhanNonClassMethodCall
961 PhanParamTooMany
521 PhanStaticCallToNonStatic
398 PhanTypeMissingReturn
240 PhanParamSignatureMismatchInternal
115 PhanDeprecatedProperty
52 PhanParamTooFew
7 PhanCompatiblePHP7

Most common backward incompatibilities & how to fix it !

preg_replace /e modifier is not longer supported

echo preg_replace('/(string)/e', 'strtoupper("\0")', 'teststringtest');// error thrown : PHP Warning:  preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead in test.php on line 3

should be replaced by preg_replace_callback with an anonymous function :

echo preg_replace_callback('/(string)/', function ($matches) {return strtoupper($matches[0]); }, 'teststringtest');

PHP4 style constructor

PHP 7 will emit E_DEPRECATED if a PHP 4 constructor is the only constructor defined within a class.

class fooclass {
protected $foo = null;
// A constructor in PHP 4 and 5
function fooclass() {
$this->foo = 'foo';
}
}
// error thrown : PHP Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; fooclass has a deprecated constructor in ./test.php on line 2

should be replaced by :

class fooclass {
protected $foo = null;
function __construct() {
$this->foo = 'foo';
}
}

Static calls to non-static methods raise e_deprecated error

Static calls to methods that are not declared static are deprecated, and may be removed in the future.

<?php
class foo {
function bar() {
echo 'thomas';
}
}
foo::bar();
PHP Deprecated: Non-static method foo::bar() should not be called statically in ./test.php on line 8

must be replaced by :

<?php
class foo {
static function bar() {
echo 'thomas';
}
}
foo::bar();

Signature mismatch during inheritance raise E_WARNING

<?php
class fooParent {
function bar(string $a) {
}
}
class fooChild extends fooParent {
function bar() {
echo 'thomas';
}
}
// error : PHP Warning: Declaration of fooChild::bar() should be compatible with fooParent::bar(string $a) in ./test.php on line 11

Corrected :

<?php
class fooParent {
function bar(string $a) {
}
}
class fooChild extends fooParent {
function bar(string $a) {
echo 'thomas';
}
}

I hope this story will help you to migrate your application, and make this less painful. Don’t forget that all incompatibilities are listed on PHP manual here and here with an how to correct.

Colomb Thomas

Written by

Software Engineer

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade