Sign In Start Free Trial
Account

Add to playlist

Create a Playlist

Modal Close icon
You need to login to use this feature.
  • Book Overview & Buying PHP 7 Programming Cookbook
  • Table Of Contents Toc
  • Feedback & Rating feedback
PHP 7 Programming Cookbook

PHP 7 Programming Cookbook

By : Bierer
4.1 (8)
close
close
PHP 7 Programming Cookbook

PHP 7 Programming Cookbook

4.1 (8)
By: Bierer

Overview of this book

PHP 7 comes with a myriad of new features and great tools to optimize your code and make your code perform faster than in previous versions. Most importantly, it allows you to maintain high traffic on your websites with low-cost hardware and servers through a multithreading web server. This book demonstrates intermediate to advanced PHP techniques with a focus on PHP 7. Each recipe is designed to solve practical, real-world problems faced by PHP developers like yourself every day. We also cover new ways of writing PHP code made possible only in version 7. In addition, we discuss backward-compatibility breaks and give you plenty of guidance on when and where PHP 5 code needs to be changed to produce the correct results when running under PHP 7. This book also incorporates the latest PHP 7.x features. By the end of the book, you will be equipped with the tools and skills required to deliver efficient applications for your websites and enterprises.
Table of Contents (16 chapters)
close
close
15
Index

Creating a PHP 5 to PHP 7 code converter

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.

Getting ready

The PHP 5 to PHP 7 Code Converter does two things:

  • Scans your code file and converts PHP 5 functionality that has been removed to its equivalent in PHP 7
  • Adds comments with // WARNING where changes in language usage have occurred, but where a re-write is not possible

    Note

    Please 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.

How to do it...

  1. In a new class 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( [
  2. Next, we start passing a series of key/value pairs. The key is a regular expression, which is processed against the string. Any matches are passed to the callback, which is represented as the value part of the key/value pair. We check for opening and closing tags that have been removed from PHP 7:
        // 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 '?>';
            },
  3. Next is a series of warnings when certain operations are detected and there is a potential code-break between how they're handled in PHP 5 versus PHP 7. In all these cases, the code is not re-written. Instead, an inline comment with the word 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];
                }
            },
  4. Any attempts to use << 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;
            },

    Note

    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.

  5. Next, the converter rewrites any usage of 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] . ');';
            },
  6. Finally, any attempt to use 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);
    }

How it works...

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;

See also

For more information on backwards incompatible changes, please refer to http://php.net/manual/en/migration70.incompatible.php.

Visually different images
CONTINUE READING
83
Tech Concepts
36
Programming languages
73
Tech Tools
Icon Unlimited access to the largest independent learning library in tech of over 8,000 expert-authored tech books and videos.
Icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Icon 50+ new titles added per month and exclusive early access to books as they are being written.
PHP 7 Programming Cookbook
notes
bookmark Notes and Bookmarks search Search in title playlist Add to playlist download Download options font-size Font size

Change the font size

margin-width Margin width

Change margin width

day-mode Day/Sepia/Night Modes

Change background colour

Close icon Search
Country selected

Close icon Your notes and bookmarks

Confirmation

Modal Close icon
claim successful

Buy this book with your credits?

Modal Close icon
Are you sure you want to buy this book with one of your credits?
Close
YES, BUY

Submit Your Feedback

Modal Close icon
Modal Close icon
Modal Close icon