# Preface

## Who is this book for

This is book is for PHP developers looking to jump into PHP 7. You’ll need previous experience with PHP in order to understand the topics and examples we’ll cover. The more you know about PHP 5 and OOP, the more you’ll understand why some of the changes are important and how they’ll impact your development.

If you’re a manager or leader of a team looking to work in PHP 7, this book will help your developers quickly catch up on all the changes they need to know about, and even expose some new features they can take advantage of for faster, better development.

## Contents

Chapter 1 summarizes the addition of scalar type hints. This allows your function parameters to explicitly require scalar types like string, int, float, or bool.

Chapter 2 covers the declaration of function return types, including the scalar types mentioned in chapter 1.

In Chapter 3 we explore the brand new “Spaceship Operator” which drastically simplifies 3-way comparison of two expressions.

Chapter 4 introduces another new operator, the “Null Coalesce Operators”. It’s a lot like ?: but with a built-in isset() check.

Chapter 5 demonstrates how to easily add Unicode characters to strings using a new \u{...} escape sequence.

Chapter 6 reviews how anonymous classes can be used to create classes on-the-fly, which is particularly useful for mocking and implementing simple interfaces (like loggers and observers).

Chapter 7 highlights the new ability to include multiple classes from a namespace with a single use statement.

Chapter 8 introduces the new Closure:call method which drastically simplifies binding your closures to objects at call-time.

Chapter 9 shows how generator can now return final values.

Chapter 10 explores how generators can yield from arrays, iterators, and other generators (insert Xzibit “yo dawg” joke here).

In Chapter 11 we see how PHP 7 drastically simplifies the process of generating strong random numbers for security-critical applications.

Chapter 12 demonstrates how to safely and easily perform integer division.

Chapter 13 unveils the new preg_replace_callback_array function for executing different callbacks per regular expression.

Chapter 14 covers the new IntlChar class, which helps you work with Unicode characters.

Chapter 15 shows how PHP 7 is dramatically faster than previous versions.

Chapter 16 describes how syntax is more consistent and flexible.

Chapter 17 explains how previously-reserved keywords can be used for property, constant, and method names. It contains a full list of such words.

Chapter 18 walks through the new changes to engine errors and exceptions.

Chapter 19 highlights the backwards-compatible improvements to the existing assert() feature.

Chapter 20 touches on how define() now supports array constants.

Chapter 21 demonstrates how to safely unserialize untrusted data by whitelisting which classes can be unserialized.

Chapter 22 talks about configuring session options by passing them into session_start().

Chapter 23 outlines the enhancements made to the Reflection API.

Chapter 24 shows how some integer behavior has changed in PHP 7.

Chapter 25 touches on division by zero, and how it works in the latest version of PHP.

Chapter 26 covers the new JSON library used by PHP, including a couple minor changes it introduces.

Chapter 27 demonstrates the inconsistencies in PHP 5’s foreach loops and how its behavior differs from PHP 7.

Chapter 28 describes some adjustments to the behavior of the list() construct.

Chapter 29 explains some of the changes made to function parameter behavior.

Chapter 30 unveils an old bug with custom session handlers and how PHP 7 resolves it.

Chapter 31 briefly touches on octals and how PHP 7 handles invalid ones.

Chapter 32 discusses the deprecation of PHP 4-style constructors.

Chapter 33 covers why manual salt generation is now deprecated in the password hashing API.

Chapter 34 lists all of the previously-deprecated functionality which has been fully removed from PHP 7.

Chapter 35 talks about the removal of alternative PHP tags.

Chapter 36 describes how several E_STRICT notices have been changed to other types.

Chapter 37 shows how multiple default cases are no longer permitted within a switch block.

Chapter 38 demonstrates PHP 5’s inconsistent handling of hexadecimal strings and why that incomplete functionality was removed.

Chapter 39 lists the SAPIs which are no longer supported or maintained.

Chapter 40 briefly highlights the removal of that annoying timezone warning.

And finally, the last section of the book includes a detailed list of all the breaking changes you’ll need to watch out for when migrating to PHP 7.

## Other resources

These official PHP resources were a huge help during the creation of this book, and you may find them useful:

There are plenty of other great resources out there too, including some paid and some free ones:

(Any commercial products or services listed here have not been tested or endorsed by the author - they are simply provided as a jumping-off point for your continued PHP 7 education.)

## Acknowledgements

I’d like to thank the following people for making this book possible:

• All the programmers, testers, documentation writers, RFC authors, and everyone else who has contributed to the success of PHP. I’d have nothing to write about if it wasn’t for you.
• The PHP community for sharing knowledge and expertise, thereby creating this amazing ecosystem for all developers.
• Mike Spinosa, Scott Greenwell, Ben Thomas, and the whole team at Unleashed Technologies for encouraging and promoting my continuous growth.
• Phil Sturgeon for being the catalyst behind my increased community involvement.

### PHP Wiki and Documentation Content

This book includes some content from the PHP wiki, RFCs, and documentation. This content is licensed under CC BY 3.0. All usages (and any modifications) will be noted immediately adjacent to the content within this book.

# Getting Started with PHP 7

Builds for PHP 7.0 and 7.1 are now available from both official and community repositories. In most cases, these new versions can be easily installed using your system’s package manager.

## Ubuntu 14.04 and 16.04+

Ondřej Surý provides a PPA for installing PHP 7.0 and 7.1. The latest release can be installed using these commands:

(Replace 7.0 with 7.1 if desired)

The full list of available packages can be found here: https://launchpad.net/~ondrej/+archive/ubuntu/php/+packages?field.name_filter=php7.0

## Debian 8 & 9

Ondřej Surý also provides PHP 7.0 and 7.1 packages for Debian which can be installed using these commands:

## Debian 6 & 7

PHP 7.0 can be installed using the Dotdeb repository:

Add these two lines to your /etc/apt/sources.list file, replacing <distribution> with either squeeze, wheezy, or jessie:

Install PHP 7:

The full list of available packages can be found here: http://packages.dotdeb.org/pool/all/p/php7.0/

## CentOS / RHEL

PHP 7 can be installed using the Webstatic Yum repository:

If you’re using CentOS/RHEL 7.x, run these three commands to add the repository and install PHP 7:

If you’re using CentOS/RHEL 6.x, run these two commands to add the repository and install PHP 7:

The full list of available packages (including SAPIs and extensions) can be found here: https://webtatic.com/packages/php70/#sapi

## Mac OS X

PHP 7 can be installed using homebrew:

Or you can install it via Liip’s php-osx tool:

## Windows

PHP 7 distributions for Windows can be found on the windows.php.net website: http://windows.php.net/download#php-7.0

For local development, you could instead use third-party distributions like XAMPP or EasyPHP. Both come with PHP 7, MySQL, and a web server so you can get up-and-running fast.

## phpbrew

phpbrew is a wonderful utility which allows you to easily build and switch between different versions of PHP on the same machine. It supports all modern versions of PHP, including PHP 7.

First we need phpbrew to fetch information about available versions:

We can then install PHP 7.0, 7.1, or any other version:

## Docker

Official Docker images for PHP can be found at https://hub.docker.com/_/php/.

## Vagrant Image

Rasmus Lerdorf, the creator of PHP, provides a Vagrant box image on his GitHub: https://github.com/rlerdorf/php7dev

It’s based on Debian 8 and is pre-configured to help develop PHP apps and extensions.

## Build from Source

Documentation on compiling PHP 7:

• https://wiki.php.net/phpng
• http://www.zimuel.it/install-php-7/
• http://www.hashbangcode.com/blog/compiling-and-installing-php7-ubuntu

# Part 1 - New Features

Perhaps the most exciting part of PHP 7 are the new features! This part of the book covers these features in detail, including examples of useful applications.

## Chapter 1: Scalar Type Hints

PHP 5 introduced the ability to require function parameters to be of a certain type. This provides a safeguard against invalid uses, like passing a UNIX timestamp to a method which expects a DateTime object. It also makes it clear to other developers how the function should be used. For example, compare the following method signatures with and without type hints:

These hints were initially limited to just classes and interfaces, but was soon expanded to allow array and callable types too. PHP 7 extends this further by allowing scalar types like int, float, string and bool:

### Type Checking Modes

PHP’s flexible type system is one of its most-useful features, allowing numeric strings to be used as integers and vice-versa. This tradition is continued in PHP 7 but now you have the option of enabling strict type enforcement like you’d see in other languages (such as Java or C#). This setting can be enabled using the declare construct.

#### Weak (“Coercive”) Type Checking

“Coercive” mode is the default type checking mode in PHP 7. This is identical to how previous versions of PHP handled scalar type hints for built-in functions. For example, take a look at the method signature for the floor function:

When you pass in numeric strings or integers PHP auto-converts them to a float automatically. This behavior has simply been extended to userland functions as well.

Here’s a table showing which scalar types are accepted in “Coercive” mode based on the declared type:

Allowed types, coercive mode
Type declaration int float string bool object
int yes yes* yes† yes no
float yes yes yes† yes no
string yes yes yes yes yes‡
bool yes yes yes yes no

* Only non-NaN floats between PHP_INT_MIN and PHP_INT_MAX accepted.

† If it’s a numeric string

‡ Only if object has a __toString() method

#### Strong (“Strict”) Type Checking

PHP 7 introduces a new “strict” mode which is enabled by placing declare(strict_types=1); at the top of your script like so:

This declaration enables strict mode for all uses in the entire file, including built-in PHP function calls and return values (see next chapter). It does not affect any included files nor any other files which include it.

Strict mode essentially requires you to pass in exact types declared. If you don’t, a TypeError will be thrown. For example, in strict mode, you cannot use numeric strings when a float or int is expected (like you can in weak/coercive mode):

There’s one exception to this rule though, which is that float declarations can accept int values:

Allowed types, strict mode
Type declaration int float string bool object
int yes no no no no
float yes* yes no no no
string no no yes no no
bool no no no yes no

* Allowed due to widening primitive conversion

### Mixing Modes

Because the directive is set per-file, it’s entirely possible to mix modes in your application. For example, your strictly-checked app could use a weakly-checked library (or vice versa) without any issues or complications.

### Backwards Compatibility

You may no longer create classes named int, float, string or bool as these would conflict with the new scalar type hints.

## Chapter 3: Combined Comparison (Spaceship) Operator

PHP 7 introduces a new three-way comparison operator <=> (T_SPACESHIP) which takes two expressions: (expr) <=> (expr). It compares both sides of the expression and, depending on the result, returns one of three values:

 0 If both expressions are equal 1 If the left is greater -1 If the right is greater

You may be familiar with this if you’ve worked with existing comparison functions like strcmp before.

It has the same precedence as the equality operator (==, ===, !=, !==) and behaves identically to the existing comparison operators (<, <=, ==, >=, >).

### Comparing Values

You can compare everything from scalar values (like ints and floats) to arrays and even objects too. Here are some examples from the relevant RFC:

### Sorting

Perhaps the best application of this operator is to simplify sorting, as functions like usort expect you to perform a comparison and return -1, 0, or 1 accordingly:

This simplification is especially apparent when comparing objects by some property value:

Without the comparison operator, these functions would be much more complex:

### Sorting by multiple values

You can take advantage of the array comparison behavior to easily sort by multiple fields:

## Chapter 5: Unicode Codepoint Escape Syntax

PHP’s lack of native Unicode support can make things difficult when coding for the web. While libraries like iconv and mbstring have simplified working with strings, there were no simple mechanisms available to create Unicode characters or strings without converting them from an HTML or JSON representation:

PHP 7 finally introduces native support for Unicode character escape sequences within strings, just like you’d see in Ruby or ECMAScript 6:

This makes it much easier (and quicker) to embed Unicode characters, especially ones that aren’t easily typed. These can be used in strings alongside other characters too. For example, here’s the U+202E RIGHT-TO-LEFT OVERRIDE character being used to display the string in reverse:

You can omit leading 0s if you’d like:

### Why the {}s?

Some other languages (C/C++/Java) use a format without the {} characters: \uXXXX. Unfortunately this limits their use to the Basic Multilingual Plane (U+0000 to U+FFFF). However, Unicode supports other characters beyond 16 bits.

For example, if we wanted to represent the U+1F427 PENGUIN emoji, our escape sequence would look something like this: \u1F427. Most languages would intepret this as U+1F42 GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA plus a 7, which is not what we want. In these languages, you’d have to encode it using two 16-bit sequences like this: \uD83D\uDC27. This isn’t very clear though.

Wrapping with {} characters allows us to easily go beyond that 16-bit limitation without sacrficing clarity: \u{1F427}

### Limitations

This feature follows the behavior of all other escape sequences in PHP - they can only be used within double-quoted strings and heredocs:

And like other sequences such as \t, they will not be expanded when they occur in single-quoted strings or nowdocs:

### Backwards Compatibility

Double-quoted strings and heredocs containing \u{ followed by an invalid sequence will now result in an error. This can be avoided by escaping the leading backslash with another backslash (\\u{).

# Part 2 - Language Changes & Improvements

PHP 7 includes several major improvements to the language, as well as some changes to existing features.

Learn about the features and changes which make PHP 7 faster and more flexible than ever!

## Chapter 15: Performance

PHP 7 is faster than ever. Most real-world applications will see a 100%+ boost in performance simply by upgrading! Here are some actual benchmarks from the Zend Performance Team1:

This improvement is largely due to the PHPNG (PHP Next-Gen) project which refactored the Zend Engine to be super-performant. Some of the under-the-hood changes include things like:

• Using more-compact data structures
• Reducing the number of heap allocations and deallocations
• Utilizing native thread local storage

The net result is a faster PHP which also uses less memory. These changes also pave the way for future improvements, like JIT compilation, which will make PHP even faster.

# Part 3 - Deprecations & Removals

PHP 7 deprecates a couple features and removes several others which worked in previous versions of PHP. You’ll want to adjust your code accordingly before upgrading to PHP 7.

# Appendix - Backward Compatibility Breaks

If you’re coming from a modern version of PHP (like 5.5 or 5.6), most of your code will probably work fine as-is. Nevertheless, we’ll cover most of the important breaking changes in this section so you’ll be prepared to fix any such issues in your projects.

The majority of these BC breaks were covered in previous chapters. We’ll link back to those sections as needed.

This list comes directly from the php-src UPGRADING document as of 7 November 2015. It may not be exhaustive. Please check https://github.com/php/php-src/blob/PHP-7.0.0/UPGRADING for the latest version.

## Language Changes

### Variable handling

#### Left-to-right parsing

Indirect variable, property and method references are now interpreted with left-to-right semantics. Some examples:

To restore the previous behavior add explicit curly braces:

#### Global Keywords

The global keyword now only accepts simple variables. Instead of

it is now required to write the following:

#### Parenthesis influencing behavior

Parentheses around variables or function calls no longer have any influence on behavior. For example the following code, where the result of a function call is passed to a by-reference function

will now throw a strict standards error regardless of whether parentheses are used. Previously no notice was generated in the second case.

#### By-reference assignment ordering

Array elements or object properties that are automatically created during by-reference assignments will now result in a different order. For example

now results in the array [“a” ⇒ 1, “b” ⇒ 1], while previously the result was [“b” ⇒ 1, “a” ⇒ 1];

### list() behavior

#### Variable assignment order

list() will no longer assign variables in reverse order. For example

#### Negative bitwise shifting

Bitwise shifts by negative numbers will now throw an ArithmeticError:

#### Left bitwise shifts

Left bitwise shifts by a number of bits beyond the bit width of an integer will always result in 0:

Previously the behavior of this code was dependent on the used CPU architecture. For example on x86 (including x86-64) the result was int(1), because the shift operand was wrapped.

#### Right bitwise shifts

Similarly right bitwise shifts by a number of bits beyond the bit width of an integer will always result in 0 or -1 (depending on sign):

### String handling

Strings that contain hexadecimal numbers are no longer considered to be numeric and don’t receive special treatment anymore. Some examples of the new behavior:

filter_var() can be used to check if a string contains a hexadecimal number or convert such a string into an integer:

#### Unicode escape sequence

Due to the addition of the Unicode Codepoint Escape Syntax for double-quoted strings and heredocs, “\u{“ followed by an invalid sequence will now result in an error:

To avoid this the leading backslash should be escaped:

However, “\u” without a following { is unaffected. As such the following code won’t error and will work the same as before:

### Error handling

#### Errors as throwables

There are now two exception classes: Exception and Error. Both classes implement a new interface Throwable. Type hints in exception handling code may need to be changed to account for this.

#### Fatal errors

Some fatal errors and recoverable fatal errors now throw an Error instead. As Error is a separate class from Exception, these exceptions will not be caught by existing try/catch blocks.

For the recoverable fatal errors which have been converted into an exception, it is no longer possible to silently ignore the error from an error handler. In particular, it is no longer possible to ignore type hint failures.

#### Parser errors

Parser errors now generate a ParseError that extends Error. Error handling for eval()s on potentially invalid code should be changed to catch ParseError in addition to the previous return value / error_get_last() based handling.

#### Internal class constructor failures

Constructors of internal classes will now always throw an exception on failure. Previously some constructors returned NULL or an unusable object.

#### Reclassification of E_STRICT

The error level of some E_STRICT notices has been changed.

### Other language changes

#### Static calls to non-static methods

Removed support for static calls to non-static methods from an incompatible $this context. In this case$this will not be defined, but the call will be allowed with a deprecation notice. An example:

Note that this only applies to calls from an incompatible context. If class B extended from A the call would be allowed without any notices.

#### Reserved words

It is no longer possible to use the following class, interface and trait names (case-insensitive):

This applies to class/interface/trait declarations, class_alias() and use statements.

Furthermore the following class, interface and trait names are now reserved for future use, but do not yet throw an error when used:

#### Parenthesis requirement for yield

The yield language construct no longer requires parentheses when used in an expression context. It is now a right-associative operator with precedence between the “print” and “⇒” operators. This can result in different behavior in some cases, for example:

#### Other removals

• Removed ASP (<%) and script (<script language=php>) tags. (RFC: https://wiki.php.net/rfc/remove_alternative_php_tags)
• Removed support for assigning the result of new by reference.
• Removed support for scoped calls to non-static methods from an incompatible $this context. See details in https://wiki.php.net/rfc/incompat_ctx. • Removed support for #-style comments in ini files. Use ;-style comments instead. • $HTTP_RAW_POST_DATA is no longer available. Use the php://input stream instead.

## Standard Library Changes

• substr() now returns an empty string instead of FALSE when the truncation happens on boundaries.
• call_user_method() and call_user_method_array() no longer exists.
• ob_start() no longer issues an E_ERROR, but instead an E_RECOVERABLE_ERROR in case an output buffer is created in an output buffer handler.
• The internal sorting algorithm has been improved, what may result in different sort order of elements that compare as equal.
• Removed dl() function on fpm-fcgi.
• setcookie() with an empty cookie name now issues an E_WARNING and doesn’t send an empty set-cookie header line anymore.

## Other Changes

### Curl

• Removed support for disabling the CURLOPT_SAFE_UPLOAD option. All curl file uploads must use the curl_file / CURLFile APIs.

### Date

• Removed \$is_dst parameter from mktime() and gmmktime().

### DBA

• dba_delete() now returns false if the key was not found for the inifile handler, too.

### GMP

• Requires libgmp version 4.2 or newer now.
• gmp_setbit() and gmp_clrbit() now return FALSE for negative indices, making them consistent with other GMP functions.

### Intl

• Removed deprecated aliases datefmt_set_timezone_id() and IntlDateFormatter::setTimeZoneID(). Use datefmt_set_timezone() and IntlDateFormatter::setTimeZone() instead.

### libxml

• Added LIBXML_BIGLINES parser option. It’s available starting with libxml 2.9.0 and adds suppport for line numbers >16-bit in the error reporting.

### Mcrypt

• Removed deprecated mcrypt_generic_end() alias in favor of mcrypt_generic_deinit().
• Removed deprecated mcrypt_ecb(), mcrypt_cbc(), mcrypt_cfb() and mcrypt_ofb() functions in favor of mcrypt_encrypt() and mcrypt_decrypt() with an MCRYPT_MODE_* flag.

### Session

• session_start() accepts all INI settings as array. e.g. [‘cache_limiter’⇒‘private’] sets session.cache_limiter=private. It also supports ‘read_and_close’ which closes session data immediately after read data.
• Save handler accepts validate_sid(), update_timestamp() which validates session ID existence, updates timestamp of session data. Compatibility of old user defined save handler is retained.
• SessionUpdateTimestampHandlerInterface is added. validateSid(), updateTimestamp() is defined in the interface.
• session.lazy_write(default=On) INI setting enables only write session data when session data is updated.

### OpenSSL

• Removed the “rsa_key_size” SSL context option in favor of automatically setting the appropriate size given the negotiated crypto algorithm.
• Removed “CN_match” and “SNI_server_name” SSL context options. Use automatic detection or the “peer_name” option instead.

### PCRE:

• Removed support for /e (PREG_REPLACE_EVAL) modifier. Use preg_replace_callback() instead.

### PDO_pgsql:

• Removed PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT attribute in favor of ATTR_EMULATE_PREPARES.

### Standard:

• Removed string category support in setlocale(). Use the LC_* constants instead.
• Removed set_magic_quotes_runtime() and its alias magic_quotes_runtime().

### JSON:

• Rejected RFC 7159 incompatible number formats in json_decode string - top level (07, 0xff, .1, -.1) and all levels ([1.], [1.e1])
• Calling json_decode with 1st argument equal to empty PHP string or value that after casting to string is empty string (NULL, FALSE) results in JSON syntax error.

### Stream:

• Removed set_socket_blocking() in favor of its alias stream_set_blocking().

### XSL:

• Removed xsl.security_prefs ini option. Use XsltProcessor::setSecurityPrefs() instead.

# Part 2 - Language Changes & Improvements

1https://www.zend.com/en/resources/php7_infographic