• Upgrade guides

PHP 7.0 to 7.2 migration

This guide details the changes between PHP 7.0 and 7.2, preparing you for the November/December 2018 transition from PHP 7.0 to PHP 7.2 on the Includable Platform.

Upgrade timeline

To be able to test if your module works correctly, we will first release the PHP upgrade on our development environment (sadev.io), giving you a chance to check if everything still works as expected. The timeline for this upgrade is as follows:

  • November 21, 2018: PHP 7.2 upgrade on sadev.io
  • December 19, 2018: PHP 7.2 upgrade on production

Migration details

New features

  • Nullable types Type declarations for parameters and return values can now be marked as nullable by prefixing the type name with a question mark. This signifies that as well as the specified type, NULL can be passed as an argument, or returned as a value, respectively.
  • Void functions A void return type has been introduced. Functions declared with void as their return type must either omit their return statement altogether, or use an empty return statement. NULL is not a valid return value for a void function.
  • Symmetric array destructuring The shorthand array syntax ([]) may now be used to destructure arrays for assignments (including within foreach), as an alternative to the existing list() syntax, which is still supported.
  • Class constant visibility Support for specifying the visibility of class constants has been added.
  • Multi catch exception handling Multiple exceptions per catch block may now be specified using the pipe character (|). This is useful for when different exceptions from different class hierarchies are handled the same.
  • Iterable pseudo-type A new pseudo-type (similar to callable) called iterable has been introduced. It may be used in parameter and return types, where it accepts either arrays or objects that implement the Traversable interface.
  • Support for keys in list() You can now specify keys in list(), or its new shorthand [] syntax. This enables destructuring of arrays with non-integer or non-sequential keys.
  • Support for negative string offsets Support for negative string offsets has been added to the string manipulation functions accepting offsets, as well as to string indexing with [] or {}. In such cases, a negative offset is interpreted as being an offset from the end of the string.
  • Convert callables to Closures A new static method Closure::fromCallable() has been introduced to the Closure class to allow for callables to be easily converted into Closure objects.
  • New object type A new type, object, has been introduced that can be used for (contravariant) parameter typing and (covariant) return typing of any objects.
  • Abstract method overriding Abstract methods can now be overridden when an abstract class extends another abstract class.
  • Sodium is now a core extension The modern Sodium cryptography library has now become a core extension in PHP.
  • Password hashing with Argon2 Argon2 has been added to the password hashing API.
  • Parameter type widening Parameter types from overridden methods and from interface implementations may now be omitted. This is still in compliance with LSP, since parameters types are contravariant.
  • Allow a trailing comma for grouped namespaces A trailing comma can now be added to the group-use syntax introduced in PHP 7.0.
  • pack() and unpack() endian support The pack() and unpack() functions now support float and double in both little and big endian.
  • Enhancements to the EXIF extension The EXIF extension has been updated to support a much larger range of formats. This means that their format specific tags are now properly translated when parsing images with the exif_read_data() function.
  • Enhancements to the ZIP extension Read and write support for encrypted archives has been added.

Backwards incompatible changes

  • Throw on passing too few function arguments Previously, a warning would be emitted for invoking user-defined functions with too few arguments. Now, this warning has been promoted to an Error exception. This change only applies to user-defined functions, not internal functions.
  • Invalid class, interface, and trait names The following names cannot be used to name classes, interfaces, or traits: void, iterable
  • Numerical string conversions now respect scientific notation Integer operations and conversions on numerical strings now respect scientific notation.
  • Fixes to mt_rand() algorithm mt_rand() will now default to using the fixed version of the Mersenne Twister algorithm.
  • rand() aliased to mt_rand() and srand() aliased to mt_srand() rand() and srand() have now been made aliases to mt_rand() and mt_srand(), respectively.
  • Disallow the ASCII delete control character in identifiers The ASCII delete control character (0x7F) can no longer be used in identifiers that are not quoted.
  • Do not call destructors on incomplete objects Destructors are now never called for objects that throw an exception during the execution of their constructor. In previous versions this behavior depended on whether the object was referenced outside the constructor (e.g. by an exception backtrace).
  • call_user_func() handling of reference arguments call_user_func() will now always generate a warning upon calls to functions that expect references as arguments. Previously this depended on whether the call was fully qualified.
  • The empty index operator is not supported for strings anymore Applying the empty index operator to a string (e.g. $str[] = $x) throws a fatal error instead of converting silently to array.
  • Array ordering when elements are automatically created during by reference assignments has changed The order of the elements in an array has changed when those elements have been automatically created by referencing them in a by reference assignment.
  • Sort order of equal elements The internal sorting algorithm has been improved, what may result in different sort order of elements, which compare as equal, than before.
  • $options parameter of unserialize() The allowed_classes element of the $options parameter of unserialize() is now strictly typed, i.e. if anything other than an array or a boolean is given, unserialize() returns FALSE and issues an E_WARNING.
  • DateTime constructor incorporates microseconds DateTime and DateTimeImmutable now properly incorporate microseconds when constructed from the current time, either explicitly or with a relative string (e.g. "first day of next month"). This means that naive comparisons of two newly created instances will now more likely return FALSE instead of TRUE.
  • Fatal errors to Error exceptions conversions In the Date extension, invalid serialization data for DateTime or DatePeriod classes, or timezone initialization failure from serialized data, will now throw an Error exception from the __wakeup() or __set_state() methods, instead of resulting in a fatal error. In the Zip extension, the ZipArchive::addGlob() method will now throw an Error exception instead of resulting in a fatal error if glob support is not available.
  • Lexically bound variables cannot reuse names Variables bound to a closure via the use construct cannot use the same name as any superglobals, $this, or any parameter. For example, all of these function definition will result in a fatal error.
  • long2ip() parameter type change long2ip() now expects an int instead of a string.
  • Changes to mb_ereg() and mb_eregi() parameter semantics The third parameter to the mb_ereg() and mb_eregi() functions (regs) will now be set to an empty array if nothing was matched. Formerly, the parameter would not have been modified.
  • Prevent number_format() from returning negative zero Previously, it was possible for the number_format() function to return -0. Whilst this is perfectly valid according to the IEEE 754 floating point specification, this oddity was not desirable for displaying formatted numbers in a human-readable form.
  • Convert numeric keys in object and array casts Numeric keys are now better handled when casting arrays to objects and objects to arrays (either from explicit casting or by settype()).
  • Disallow passing NULL to get_class() Previously, passing NULL to the get_class() function would output the name of the enclosing class. This behaviour has now been removed, where an E_WARNING will be output instead. To achieve the same behaviour as before, the argument should simply be omitted.
  • Warn when counting non-countable types An E_WARNING will now be emitted when attempting to count() non-countable types (this includes the sizeof() alias function).
  • gettype() return value on closed resources Previously, using gettype() on a closed resource would return a string of "unknown type". Now, a string of "resource (closed)" will be returned.
  • is_object() and __PHP_Incomplete_Class Previously, using is_object() on the __PHP_Incomplete_Class class would return FALSE. Now, TRUE will be returned.
  • Promote the error level of undefined constants Unqualified references to undefined constants will now generate an E_WARNING (instead of an E_NOTICE). In the next major version of PHP, they will generate Error exceptions.
  • Checks on default property values of traits Compatibility checks upon default trait property values will no longer perform casting.
  • object for class names The object name was previously soft-reserved in PHP 7.0. This is now hard-reserved, prohibiting it from being used as a class, trait, or interface name.
  • array_unique() with SORT_STRING While array_unique() with SORT_STRING formerly copied the array and removed non-unique elements (without packing the array afterwards), now a new array is built by adding the unique elements. This can result in different numeric indexes.
  • bcmod() changes with floats The bcmod() function no longer truncates fractional numbers to integers. As such, its behavior now follows fmod(), rather than the % operator. For example bcmod('4', '3.5') now returns 0.5 instead of 1.
  • Hashing functions and non-cryptographic hashes The hash_hmac(), hash_hmac_file(), hash_pbkdf2(), and hash_init() (with HASH_HMAC) functions no longer accept non-cryptographic hashes.
  • json_decode() function options The json_decode() function option,JSON_OBJECT_AS_ARRAY, is now used if the second parameter (assoc) is NULL. Previously, JSON_OBJECT_AS_ARRAY was always ignored.
  • rand() and mt_rand() output Sequences generated by rand() and mt_rand() for a specific seed may differ from earlier versions due to the fixing of a modulo bias bug in the implementation.
  • Changes to date_parse_from_format() The zone element of the array returned by date_parse_from_format() represents seconds instead of minutes now, and its sign is inverted. For instance -120 is now 7200.

Deprecations

  • Eval option for mb_ereg_replace() and mb_eregi_replace() The e pattern modifier has been deprecated for the mb_ereg_replace() and mb_eregi_replace() functions.
  • Unquoted strings Unquoted strings that are non-existent global constants are taken to be strings of themselves. This behaviour used to emit an E_NOTICE, but will now emit an E_WARNING. In the next major version of PHP, an Error exception will be thrown instead.
  • __autoload() method The __autoload() method has been deprecated because it is inferior to spl_autoload_register() (due to it not being able to chain autoloaders), and there is no interoperability between the two autoloading styles.
  • $php_errormsg Given that the preferred way of retrieving error information on non-fatal erros is by using error_get_last(), this global variable has been deprecated.
  • create_function() function Given the security issues of this function (being a thin wrapper around eval()), this dated function has now been deprecated. The preferred alternative is to use anonymous functions.
  • (unset) cast Casting any expression to this type will always result in NULL, and so this superfluous casting type has now been deprecated.
  • parse_str() without a second argument Without the second argument to parse_str(), the query string parameters would populate the local symbol table. Given the security implications of this, using parse_str() without a second argument has now been deprecated. The function should always be used with two arguments, as the second argument causes the query string to be parsed into an array.
  • each() function This function is far slower at iteration than a normal foreach, and causes implementation issues for some language changes. It has therefore been deprecated.
  • assert() with a string argument Using assert() with a string argument required the string to be eval()'ed. Given the potential for remote code execution, using assert() with a string argument has now been deprecated in favour of using boolean expressions.
  • $errcontext argument of error handlers The $errcontext argument contains all local variables of the error site. Given its rare usage, and the problems it causes with internal optimisations, it has now been deprecated. Instead, a debugger should be used to retrieve information on local variables at the error site.
  • read_exif_data() function The read_exif_data() alias has been deprecated. The exif_read_data() function should be used instead.