Backward incompatible changesChanges to error and exception handlingMany fatal and recoverable fatal errors have been converted to exceptions in PHP 7. These error exceptions inherit from the Error class, which itself implements the Throwable interface (the new base interface all exceptions inherit). This means that custom error handlers may no longer be triggered because exceptions may be thrown instead (causing new fatal errors for uncaught Error exceptions). A fuller description of how errors operate in PHP 7 can be found on the PHP 7 errors page. This migration guide will merely enumerate the changes that affect backward compatibility. set_exception_handler is no longer guaranteed to receive Exception objectsCode that implements an exception handler registered with set_exception_handler using a type declaration of Exception will cause a fatal error when an Error object is thrown. If the handler needs to work on both PHP 5 and 7, you should remove the type declaration from the handler, while code that is being migrated to work on PHP 7 exclusively can simply replace the Exception type declaration with Throwable instead.
Internal constructors always throw exceptions on failure
Previously, some internal classes would return Parse errors throw ParseError
Parser errors now throw a ParseError object. Error
handling for eval should now include a E_STRICT notices severity changes
All of the
Changes to variable handlingPHP 7 now uses an abstract syntax tree when parsing source files. This has permitted many improvements to the language which were previously impossible due to limitations in the parser used in earlier versions of PHP, but has resulted in the removal of a few special cases for consistency reasons, which has resulted in backward compatibility breaks. These cases are detailed in this section. Changes to the handling of indirect variables, properties, and methodsIndirect access to variables, properties, and methods will now be evaluated strictly in left-to-right order, as opposed to the previous mix of special cases. The table below shows how the order of evaluation has changed.
Code that used the old right-to-left evaluation order must be rewritten to explicitly use that evaluation order with curly braces (see the above middle column). This will make the code both forwards compatible with PHP 7.x and backwards compatible with PHP 5.x.
This also affects the
Changes to list handlinglist no longer assigns variables in reverse order
list will now assign values to variables in the
order they are defined, rather than reverse order. In general, this only
affects the case where list is being used in
conjunction with the array
Output of the above example in PHP 5: array(3) { [0]=> int(3) [1]=> int(2) [2]=> int(1) } Output of the above example in PHP 7: array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) } In general, it is recommended not to rely on the order in which list assignments occur, as this is an implementation detail that may change again in the future. Empty list assignments have been removedlist constructs can no longer be empty. The following are no longer allowed:
list cannot unpack stringslist can no longer unpack string variables. str_split should be used instead. Array ordering when elements are automatically created during by reference assignments has changedThe order of the elements in an array has changed when those elements have been automatically created by referencing them in a by reference assignment. For example:
Output of the above example in PHP 5: array(2) { ["b"]=> &int(1) ["a"]=> &int(1) } Output of the above example in PHP 7: array(2) { ["a"]=> &int(1) ["b"]=> &int(1) } Parentheses around function arguments no longer affect behaviourIn PHP 5, using redundant parentheses around a function argument could quiet strict standards warnings when the function argument was passed by reference. The warning will now always be issued.
The above example will output: Notice: Only variables should be passed by reference in /tmp/test.php on line 13 Changes to foreachMinor changes have been made to the behaviour of the foreach control structure, primarily around the handling of the internal array pointer and modification of the array being iterated over. foreach no longer changes the internal array pointerPrior to PHP 7, the internal array pointer was modified while an array was being iterated over with foreach. This is no longer the case, as shown in the following example:
Output of the above example in PHP 5: int(1) int(2) bool(false) Output of the above example in PHP 7: int(0) int(0) int(0) foreach by-value operates on a copy of the arrayWhen used in the default by-value mode, foreach will now operate on a copy of the array being iterated rather than the array itself. This means that changes to the array made during iteration will not affect the values that are iterated. foreach by-reference has improved iteration behaviourWhen iterating by-reference, foreach will now do a better job of tracking changes to the array made during iteration. For example, appending to an array while iterating will now result in the appended values being iterated over as well:
Output of the above example in PHP 5: int(0) Output of the above example in PHP 7: int(0) int(1) Iteration of non-Traversable objectsIterating over a non-Traversable object will now have the same behaviour as iterating over by-reference arrays. This results in the improved behaviour when modifying an array during iteration also being applied when properties are added to or removed from the object. Changes to int handlingInvalid octal literals
Previously, octal literals that contained invalid numbers were silently
truncated ( Negative bitshiftsBitwise shifts by negative numbers will now throw an ArithmeticError:
Output of the above example in PHP 5: int(0) Output of the above example in PHP 7: Fatal error: Uncaught ArithmeticError: Bit shift by negative number in /tmp/test.php:2 Stack trace: #0 {main} thrown in /tmp/test.php on line 2 Out of range bitshiftsBitwise shifts (in either direction) beyond the bit width of an int will always result in 0. Previously, the behaviour of such shifts was architecture dependent. Changes to Division By Zero
Previously, when 0 was used as the divisor for either the divide (/) or
modulus (%) operators, an E_WARNING would be emitted and
Output of the above example in PHP 5: Warning: Division by zero in %s on line %d bool(false) Warning: Division by zero in %s on line %d bool(false) Warning: Division by zero in %s on line %d bool(false) Output of the above example in PHP 7: Warning: Division by zero in %s on line %d float(INF) Warning: Division by zero in %s on line %d float(NAN) PHP Fatal error: Uncaught DivisionByZeroError: Modulo by zero in %s line %d Changes to string handlingHexadecimal strings are no longer considered numericStrings containing hexadecimal numbers are no longer considered to be numeric. For example:
Output of the above example in PHP 5: bool(true) bool(true) int(15) string(2) "oo" Output of the above example in PHP 7: bool(false) bool(false) int(0) Notice: A non well formed numeric value encountered in /tmp/test.php on line 5 string(3) "foo" filter_var can be used to check if a string contains a hexadecimal number, and also to convert a string of that type to an int:
|
Opening tag | Closing tag |
---|---|
<% |
%> |
<%= |
%> |
<script language="php"> |
</script> |
Previously deprecated in PHP 5.6,
static calls made to a non-static method with an incompatible context will
now result in the called method having an undefined
$this
variable and a deprecation warning being issued.
<?php
class A {
public function test() { var_dump($this); }
}
// Note: Does NOT extend A
class B {
public function callNonStaticMethodOfA() { A::test(); }
}
(new B)->callNonStaticMethodOfA();
?>
Output of the above example in PHP 5.6:
Deprecated: Non-static method A::test() should not be called statically, assuming $this from incompatible context in /tmp/test.php on line 8 object(B)#1 (0) { }
Output of the above example in PHP 7:
Deprecated: Non-static method A::test() should not be called statically in /tmp/test.php on line 8 Notice: Undefined variable: this in /tmp/test.php on line 3 NULL
The yield construct no longer requires parentheses, and has been changed
to a right associative operator with precedence between
print
and =>
. This can result in
changed behaviour:
<?php
echo yield -1;
// Was previously interpreted as
echo (yield) - 1;
// And is now interpreted as
echo yield (-1);
yield $foo or die;
// Was previously interpreted as
yield ($foo or die);
// And is now interpreted as
(yield $foo) or die;
?>
Parentheses can be used to disambiguate those cases.
It is no longer possible to define two or more function parameters with the
same name. For example, the following function will trigger an
E_COMPILE_ERROR
:
<?php
function foo($a, $b, $unused, $unused) {
//
}
?>
func_get_arg, func_get_args, debug_backtrace and exception backtraces will no longer report the original value that was passed to a parameter, but will instead provide the current value (which might have been modified).
<?php
function foo($x) {
$x++;
var_dump(func_get_arg(0));
}
foo(1);?>
Output of the above example in PHP 5:
1
Output of the above example in PHP 7:
2
It is no longer possible to define two or more default blocks in a switch
statement. For example, the following switch statement will trigger an
E_COMPILE_ERROR
:
<?php
switch (1) {
default:
break;
default:
break;
}
?>
$HTTP_RAW_POST_DATA is no longer available. The
php://input
stream should be used instead.
#
comments in INI files removed
Support for prefixing comments with #
in INI files has been
removed. ;
(semi-colon) should be used instead. This change
applies to php.ini, as well as files handled by
parse_ini_file and parse_ini_string.
The JSON extension has been replaced with JSOND, causing three minor BC
breaks. Firstly, a number must not end in a decimal point (i.e.
34.
must be changed to either 34.0
or
34
). Secondly, when using scientific notation, the
e
exponent must not immediately follow a decimal point
(i.e. 3.e3
must be changed to either
3.0e3
or 3e3
).
Finally, an empty string is no longer considered valid JSON.
Previously, internal functions would silently truncate numbers produced from
float-to-integer coercions when the float was too large to represent as an
integer. Now, an E_WARNING will be emitted and null
will be returned.
Any predicate functions implemented by custom session handlers that return
either false
or -1
will be fatal errors. If any value
from these functions other than a boolean, -1
, or
0
is returned, then it will fail and an E_WARNING will be
emitted.
The internal sorting algorithm has been improved, what may result in different sort order of elements, which compare as equal, than before.
Note:
Don't rely on the order of elements which compare as equal; it might change anytime.
break
and continue
statements outside of
a loop or switch
control structure are now detected at
compile-time instead of run-time as before, and trigger an
E_COMPILE_ERROR
.
break
and continue
statements no longer
allow their argument to be a constant, and trigger a
E_COMPILE_ERROR
.
The Mhash extension has been fully integrated into the Hash extension. Therefore, it is no longer possible to detect Mhash support with extension_loaded; use function_exists instead. Furthermore, Mhash is no longer reported by get_loaded_extensions and related features.
The declare(ticks) directive does no longer leak into different compilation units.