-
Book Overview & Buying
-
Table Of Contents
-
Feedback & Rating
PHP 7 Programming Cookbook
By :
For the most part, PHP 5.x code can run unchanged on PHP 7. There are a few changes, however, that are classified as backwards incompatible. What this means is that if your PHP 5 code is written in a certain way, or uses functions that have been removed, your code will break, and you'll have a nasty error on your hands.
The PHP 5 to PHP 7 Code Converter does two things:
// WARNING where changes in language usage have occurred, but where a re-write is not possiblePlease note that after running the converter, your code is not guaranteed to work in PHP 7. You will still have to review the // WARNING tags added. At the least, this recipe will give you a good head start converting your PHP 5 code to work in PHP 7.
The core of this recipe is the new PHP 7 preg_replace_callback_array() function. What this amazing function allows you to do is to present an array of regular expressions as keys, with the value representing an independent callback. You can then pass the string through a series of transformations. Not only that, the subject of the array of callbacks can itself be an array.
Application\Parse\Convert, we begin with a scan() method, which accepts a filename as an argument. It checks to see if the file exists. If so, it calls the PHP file() function, which loads the file into an array, with each array element representing one line:public function scan($filename)
{
if (!file_exists($filename)) {
throw new Exception(
self::EXCEPTION_FILE_NOT_EXISTS);
}
$contents = file($filename);
echo 'Processing: ' . $filename . PHP_EOL;
$result = preg_replace_callback_array( [ // replace no-longer-supported opening tags
'!^\<\%(\n| )!' =>
function ($match) {
return '<?php' . $match[1];
},
// replace no-longer-supported opening tags
'!^\<\%=(\n| )!' =>
function ($match) {
return '<?php echo ' . $match[1];
},
// replace no-longer-supported closing tag
'!\%\>!' =>
function ($match) {
return '?>';
},WARNING is added: // changes in how $$xxx interpretation is handled
'!(.*?)\$\$!' =>
function ($match) {
return '// WARNING: variable interpolation
. ' now occurs left-to-right' . PHP_EOL
. '// see: http://php.net/manual/en/'
. '// migration70.incompatible.php'
. $match[0];
},
// changes in how the list() operator is handled
'!(.*?)list(\s*?)?\(!' =>
function ($match) {
return '// WARNING: changes have been made '
. 'in list() operator handling.'
. 'See: http://php.net/manual/en/'
. 'migration70.incompatible.php'
. $match[0];
},
// instances of \u{
'!(.*?)\\\u\{!' =>
function ($match) {
return '// WARNING: \\u{xxx} is now considered '
. 'unicode escape syntax' . PHP_EOL
. '// see: http://php.net/manual/en/'
. 'migration70.new-features.php'
. '#migration70.new-features.unicode-'
. 'codepoint-escape-syntax' . PHP_EOL
. $match[0];
},
// relying upon set_error_handler()
'!(.*?)set_error_handler(\s*?)?.*\(!' =>
function ($match) {
return '// WARNING: might not '
. 'catch all errors'
. '// see: http://php.net/manual/en/'
. '// language.errors.php7.php'
. $match[0];
},
// session_set_save_handler(xxx)
'!(.*?)session_set_save_handler(\s*?)?\((.*?)\)!' =>
function ($match) {
if (isset($match[3])) {
return '// WARNING: a bug introduced in'
. 'PHP 5.4 which '
. 'affects the handler assigned by '
. 'session_set_save_handler() and '
. 'where ignore_user_abort() is TRUE
. 'has been fixed in PHP 7.'
. 'This could potentially break '
. 'your code under '
. 'certain circumstances.' . PHP_EOL
. 'See: http://php.net/manual/en/'
. 'migration70.incompatible.php'
. $match[0];
} else {
return $match[0];
}
},<< or >> with a negative operator, or beyond 64, is wrapped in a try { xxx } catch() { xxx } block, looking for an ArithmeticError to be thrown: // wraps bit shift operations in try / catch
'!^(.*?)(\d+\s*(\<\<|\>\>)\s*-?\d+)(.*?)$!' =>
function ($match) {
return '// WARNING: negative and '
. 'out-of-range bitwise '
. 'shift operations will now
. 'throw an ArithmeticError' . PHP_EOL
. 'See: http://php.net/manual/en/'
. 'migration70.incompatible.php'
. 'try {' . PHP_EOL
. "\t" . $match[0] . PHP_EOL
. '} catch (\\ArithmeticError $e) {'
. "\t" . 'error_log("File:"
. $e->getFile()
. " Message:" . $e->getMessage());'
. '}' . PHP_EOL;
},PHP 7 has changed how errors are handled. In some cases, errors are moved into a similar classification as exceptions, and can be caught! Both the Error and the Exception class implement the Throwable interface. If you want to catch either an Error or an Exception, catch Throwable.
call_user_method*(), which has been removed in PHP 7. These are replaced with the equivalent using call_user_func*(): // replaces "call_user_method()" with
// "call_user_func()"
'!call_user_method\((.*?),(.*?)(,.*?)\)(\b|;)!' =>
function ($match) {
$params = $match[3] ?? '';
return '// WARNING: call_user_method() has '
. 'been removed from PHP 7' . PHP_EOL
. 'call_user_func(['. trim($match[2]) . ','
. trim($match[1]) . ']' . $params . ');';
},
// replaces "call_user_method_array()"
// with "call_user_func_array()"
'!call_user_method_array\((.*?),(.*?),(.*?)\)(\b|;)!' =>
function ($match) {
return '// WARNING: call_user_method_array()'
. 'has been removed from PHP 7'
. PHP_EOL
. 'call_user_func_array(['
. trim($match[2]) . ','
. trim($match[1]) . '], '
. $match[3] . ');';
},preg_replace() with the /e modifier is rewritten using a preg_replace_callback(): '!^(.*?)preg_replace.*?/e(.*?)$!' =>
function ($match) {
$last = strrchr($match[2], ',');
$arg2 = substr($match[2], 2, -1 * (strlen($last)));
$arg1 = substr($match[0],
strlen($match[1]) + 12,
-1 * (strlen($arg2) + strlen($last)));
$arg1 = trim($arg1, '(');
$arg1 = str_replace('/e', '/', $arg1);
$arg3 = '// WARNING: preg_replace() "/e" modifier
. 'has been removed from PHP 7'
. PHP_EOL
. $match[1]
. 'preg_replace_callback('
. $arg1
. 'function ($m) { return '
. str_replace('$1','$m', $match[1])
. trim($arg2, '"\'') . '; }, '
. trim($last, ',');
return str_replace('$1', '$m', $arg3);
},
// end array
],
// this is the target of the transformations
$contents
);
// return the result as a string
return implode('', $result);
}To use the converter, run the following code from the command line. You'll need to supply the filename of the PHP 5 code to be scanned as an argument.
This block of code, chap_01_php5_to_php7_code_converter.php, run from the command line, calls the converter:
<?php
// get filename to scan from command line
$filename = $argv[1] ?? '';
if (!$filename) {
echo 'No filename provided' . PHP_EOL;
echo 'Usage: ' . PHP_EOL;
echo __FILE__ . ' <filename>' . PHP_EOL;
exit;
}
// setup class autoloading
require __DIR__ . '/../Application/Autoload/Loader.php';
// add current directory to the path
Application\Autoload\Loader::init(__DIR__ . '/..');
// get "deep scan" class
$convert = new Application\Parse\Convert();
echo $convert->scan($filename);
echo PHP_EOL;For more information on backwards incompatible changes, please refer to http://php.net/manual/en/migration70.incompatible.php.
Change the font size
Change margin width
Change background colour