{"id":15036395,"url":"https://github.com/tpunt/php7-reference","last_synced_at":"2025-05-16T11:05:23.008Z","repository":{"id":33087844,"uuid":"36725241","full_name":"tpunt/PHP7-Reference","owner":"tpunt","description":"An overview of the features, changes, and backward compatibility breakages in PHP 7","archived":false,"fork":false,"pushed_at":"2018-08-14T01:02:59.000Z","size":120,"stargazers_count":1376,"open_issues_count":2,"forks_count":122,"subscribers_count":112,"default_branch":"master","last_synced_at":"2025-05-16T11:05:17.918Z","etag":null,"topics":["php","php7","php71","php72"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tpunt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-06-02T10:17:11.000Z","updated_at":"2025-05-09T10:07:06.000Z","dependencies_parsed_at":"2022-08-31T08:20:50.693Z","dependency_job_id":null,"html_url":"https://github.com/tpunt/PHP7-Reference","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpunt%2FPHP7-Reference","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpunt%2FPHP7-Reference/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpunt%2FPHP7-Reference/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpunt%2FPHP7-Reference/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tpunt","download_url":"https://codeload.github.com/tpunt/PHP7-Reference/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254518384,"owners_count":22084374,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["php","php7","php71","php72"],"created_at":"2024-09-24T20:31:01.861Z","updated_at":"2025-05-16T11:05:17.999Z","avatar_url":"https://github.com/tpunt.png","language":null,"readme":" - [PHP 7.2 Reference](https://github.com/tpunt/PHP7-Reference/blob/master/php72-reference.md)\n - [PHP 7.1 Reference](https://github.com/tpunt/PHP7-Reference/blob/master/php71-reference.md)\n\n---\n\n# PHP 7.0\n\nPHP 7 was released on [December 3rd, 2015](http://php.net/archive/2015.php#id2015-12-03-1). It comes\nwith a number of new features, changes, and backwards compatibility breakages\nthat are outlined below.\n\n**[Performance](#performance)**\n\n**[Features](#features)**\n* [Combined Comparison Operator](#combined-comparison-operator)\n* [Null Coalesce Operator](#null-coalesce-operator)\n* [Scalar Type Declarations](#scalar-type-declarations)\n* [Return Type Declarations](#return-type-declarations)\n* [Anonymous Classes](#anonymous-classes)\n* [Unicode Codepoint Escape Syntax](#unicode-codepoint-escape-syntax)\n* [Closure `call()` Method](#closure-call-method)\n* [Filtered `unserialize()`](#filtered-unserialize)\n* [`IntlChar` Class](#intlchar-class)\n* [Expectations](#expectations)\n* [Group `use` Declarations](#group-use-declarations)\n* [Generator Return Expressions](#generator-return-expressions)\n* [Generator Delegation](#generator-delegation)\n* [Integer Division with `intdiv()`](#integer-division-with-intdiv)\n* [`session_start()` Options](#session_start-options)\n* [`preg_replace_callback_array()` Function](#preg_replace_callback_array-function)\n* [CSPRNG Functions](#csprng-functions)\n* [Support for Array Constants in `define()`](#support-for-array-constants-in-define)\n* [Reflection Additions](#reflection-additions)\n\n**[Changes](#changes)**\n* [Loosening Reserved Word Restrictions](#loosening-reserved-word-restrictions)\n* [Uniform Variable Syntax](#uniform-variable-syntax)\n* [Exceptions in the Engine](#exceptions-in-the-engine)\n* [Throwable Interface](#throwable-interface)\n* [Integer Semantics](#integer-semantics)\n* [JSON Extension Replaced with JSOND](#json-extension-replaced-with-jsond)\n* [ZPP Failure on Overflow](#zpp-failure-on-overflow)\n* [Fixes to `foreach()`'s Behaviour](#fixes-to-foreachs-behaviour)\n* [Changes to `list()`'s Behaviour](#changes-to-lists-behaviour)\n* [Changes to Division by Zero Semantics](#changes-to-division-by-zero-semantics)\n* [Fixes to Custom Session Handler Return Values](#fixes-to-custom-session-handler-return-values)\n* [Deprecation of PHP 4-Style Constructors](#deprecation-of-php-4-style-constructors)\n* [Removal of date.timezone Warning](#removal-of-datetimezone-warning)\n* [Removal of Alternative PHP Tags](#removal-of-alternative-php-tags)\n* [Removal of Multiple Default Blocks in Switch Statements](#removal-of-multiple-default-blocks-in-switch-statements)\n* [Removal of Redefinition of Parameters with Duplicate Names](#removal-of-redefinition-of-parameters-with-duplicate-names)\n* [Removal of Dead Server APIs](#removal-of-dead-server-apis)\n* [Removal of Hex Support in Numerical Strings](#removal-of-hex-support-in-numerical-strings)\n* [Removal of Deprecated Functionality](#removal-of-deprecated-functionality)\n* [Reclassification and Removal of E_STRICT Notices](#reclassification-and-removal-of-e_strict-notices)\n* [Deprecation of Salt Option for `password_hash()`](#deprecation-of-salt-option-for-password_hash)\n* [Error on Invalid Octal Literals](#error-on-invalid-octal-literals)\n* [`substr()` Return Value Change](#substr-return-value-change)\n\n**[FAQ](#faq)**\n * [What happened to PHP 6?](#what-happened-to-php-6)\n\n## Performance\n\nUnarguably the greatest part about PHP 7 is the incredible performance boosts\nit provides to applications. This is a result of refactoring the Zend Engine to\nuse more compact data structures and less heap allocations/deallocations.\n\nThe performance gains on real world applications will vary, though many\napplications seem to receive a ~100% performance boost - with lower memory\nconsumption too!\n\nThe refactored codebase provides further opportunities for future optimisations\nas well (such as JIT compilation). So it looks like future PHP versions will\ncontinue to see performance enhancements too.\n\nPHP 7 performance chart comparisons:\n - [Turbocharging the Web with PHP 7](https://www.zend.com/en/resources/php7_infographic)\n - [Benchmarks from Rasmus's Sydney Talk](http://talks.php.net/oz15#/drupalbench)\n\n## Features\n\n### Combined Comparison Operator\nThe combined comparison operator (or spaceship operator) is a shorthand\nnotation for performing three-way comparisons from two operands. It has an\ninteger return value that can be either:\n\n* a positive integer (if the left-hand operand is greater than the right-hand operand)\n* 0 (if both operands are equal)\n* a negative integer (if the right-hand operand is greater than the left-hand operand)\n\nThe operator has the same precedence as the equality operators (`==`, `!=`,\n`===`, `!==`) and has the exact same behaviour as the other loose comparison\noperators (`\u003c`, `\u003e=`, etc). It is also non-associative like them too, so\nchaining of the operands (like `1 \u003c=\u003e 2 \u003c=\u003e 3`) is not allowed.\n\n```PHP\n// compares strings lexically\nvar_dump('PHP' \u003c=\u003e 'Node'); // int(1)\n\n// compares numbers by size\nvar_dump(123 \u003c=\u003e 456); // int(-1)\n\n// compares corresponding array elements with one-another\nvar_dump(['a', 'b'] \u003c=\u003e ['a', 'b']); // int(0)\n```\n\nObjects are not comparable, and so using them as operands with this operator\nwill result in undefined behaviour.\n\nRFC: [Combined Comparison Operator](https://wiki.php.net/rfc/combined-comparison-operator)\n\n### Null Coalesce Operator\nThe null coalesce operator (or isset ternary operator) is a shorthand notation\nfor performing `isset()` checks in the ternary operator. This is a common thing\nto do in applications, and so a new syntax has been introduced for this exact\npurpose.\n\n```PHP\n// Pre PHP 7 code\n$route = isset($_GET['route']) ? $_GET['route'] : 'index';\n\n// PHP 7+ code\n$route = $_GET['route'] ?? 'index';\n```\n\nRFC: [Null Coalesce Operator](https://wiki.php.net/rfc/isset_ternary)\n\n### Scalar Type Declarations\nScalar type declarations come in two flavours: **coercive** (default) and\n**strict**. The following types for parameters can now be enforced (either\ncoercively or strictly): strings (`string`), integers (`int`), floating-point\nnumbers (`float`), and booleans (`bool`). They augment the other types\nintroduced in the PHP 5.x versions: class names, interfaces, `array` and\n`callable`.\n\n```PHP\n// Coercive mode\nfunction sumOfInts(int ...$ints)\n{\n    return array_sum($ints);\n}\n\nvar_dump(sumOfInts(2, '3', 4.1)); // int(9)\n```\n\nTo enable strict mode, a single `declare()` directive must be placed at the top\nof the file. This means that the strictness of typing for scalars is configured\non a per-file basis. This directive not only affects the type declarations of\nparameters, but also a function's return type (see [Return Type\nDeclarations](#return-type-declarations)), built-in PHP functions, and\nfunctions from loaded extensions.\n\nIf the type-check fails, then a `TypeError` exception (see [Exceptions in the\nEngine](#exceptions-in-the-engine)) is thrown. The only leniency present in\nstrict typing is the automatic conversion of integers to floats (but not\nvice-versa) when an integer is provided in a float context.\n\n```PHP\ndeclare(strict_types=1);\n\nfunction multiply(float $x, float $y)\n{\n    return $x * $y;\n}\n\nfunction add(int $x, int $y)\n{\n    return $x + $y;\n}\n\nvar_dump(multiply(2, 3.5)); // float(7)\nvar_dump(add('2', 3)); // Fatal error: Uncaught TypeError: Argument 1 passed to add() must be of the type integer, string given...\n```\n\nNote that **only** the *invocation context* applies when the type-checking is\nperformed. This means that the strict typing applies only to function/method\ncalls, and not to the function/method definitions. In the above example, the\ntwo functions could have been declared in either a strict or coercive file, but\nso long as they're being called in a strict file, then the strict typing rules\nwill apply.\n\n**BC Breaks**\n - Classes with names `int`, `string`, `float`, and `bool` are now forbidden.\n\nRFC: [Scalar Type Declarations](https://wiki.php.net/rfc/scalar_type_hints_v5)\n\n### Return Type Declarations\nReturn type declarations enable for the return type of a function, method, or\nclosure to be specified. The following return types are supported: `string`,\n`int`, `float`, `bool`, `array`, `callable`, `self` (methods only), `parent`\n(methods only), `Closure`, the name of a class, and the name of an interface.\n\n```PHP\nfunction arraysSum(array ...$arrays): array\n{\n    return array_map(function(array $array): int {\n        return array_sum($array);\n    }, $arrays);\n}\n\nprint_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));\n/* Output\nArray\n(\n    [0] =\u003e 6\n    [1] =\u003e 15\n    [2] =\u003e 24\n)\n*/\n```\n\nWith respect to subtyping, **invariance** has been chosen for return types.\nThis simply means that when a method is either overridden in a subtyped class\nor implemented as defined in a contract, its return type must match exactly the\nmethod it is (re)implementing.\n\n```PHP\nclass A {}\nclass B extends A {}\n\nclass C\n{\n    public function test() : A\n    {\n        return new A;\n    }\n}\n\nclass D extends C\n{\n    // overriding method C::test() : A\n    public function test() : B // Fatal error due to variance mismatch\n    {\n        return new B;\n    }\n}\n```\n\nThe overriding method `D::test() : B` causes an `E_COMPILE_ERROR` because\ncovariance is not allowed. In order for this to work, `D::test()` method must\nhave a return type of `A`.\n\n```PHP\nclass A {}\n\ninterface SomeInterface\n{\n    public function test() : A;\n}\n\nclass B implements SomeInterface\n{\n    public function test() : A // all good!\n    {\n        return null; // Fatal error: Uncaught TypeError: Return value of B::test() must be an instance of A, null returned...\n    }\n}\n```\n\nThis time, the implemented method causes a `TypeError` exception (see\n[Exceptions in the Engine](#exceptions-in-the-engine)) to be thrown when\nexecuted. This is because `null` is not a valid return type - only an instance of the\nclass `A` can be returned.\n\nRFC: [Return Type Declarations](https://wiki.php.net/rfc/return_types)\n\n### Anonymous Classes\n\nAnonymous classes are useful when simple, one-off objects need to be created.\n\n```PHP\n// Pre PHP 7 code\nclass Logger\n{\n    public function log($msg)\n    {\n        echo $msg;\n    }\n}\n\n$util-\u003esetLogger(new Logger());\n\n// PHP 7+ code\n$util-\u003esetLogger(new class {\n    public function log($msg)\n    {\n        echo $msg;\n    }\n});\n```\n\nThey can pass arguments through to their constructors, extend other classes,\nimplement interfaces, and use traits just like a normal class can:\n```PHP\nclass SomeClass {}\ninterface SomeInterface {}\ntrait SomeTrait {}\n\nvar_dump(new class(10) extends SomeClass implements SomeInterface {\n    private $num;\n\n    public function __construct($num)\n    {\n        $this-\u003enum = $num;\n    }\n\n    use SomeTrait;\n});\n\n/** Output:\nobject(class@anonymous)#1 (1) {\n  [\"Command line code0x104c5b612\":\"class@anonymous\":private]=\u003e\n  int(10)\n}\n*/\n```\n\nNesting an anonymous class within another class does not give it access to any\nprivate or protected methods or properties of that outer class. In order to use\nthe outer class' protected properties or methods, the anonymous class can\nextend the outer class. To use the private or protected properties of the outer\nclass in the anonymous class, they must be passed through its constructor:\n```PHP\n\u003c?php\n\nclass Outer\n{\n    private $prop = 1;\n    protected $prop2 = 2;\n\n    protected function func1()\n    {\n        return 3;\n    }\n\n    public function func2()\n    {\n        return new class($this-\u003eprop) extends Outer {\n            private $prop3;\n\n            public function __construct($prop)\n            {\n                $this-\u003eprop3 = $prop;\n            }\n\n            public function func3()\n            {\n                return $this-\u003eprop2 + $this-\u003eprop3 + $this-\u003efunc1();\n            }\n        };\n    }\n}\n\necho (new Outer)-\u003efunc2()-\u003efunc3(); // 6\n```\n\nRFC: [Anonymous Classes](https://wiki.php.net/rfc/anonymous_classes)\n\n### Unicode Codepoint Escape Syntax\n\nThis enables a UTF-8 encoded unicode codepoint to be output in either a\ndouble-quoted string or a heredoc. Any valid codepoint is accepted, with\nleading `0`'s being optional.\n\n```PHP\necho \"\\u{aa}\"; // ª\necho \"\\u{0000aa}\"; // ª (same as before but with optional leading 0's)\necho \"\\u{9999}\"; // 香\n```\n\nRFC: [Unicode Codepoint Escape Syntax](https://wiki.php.net/rfc/unicode_escape)\n\n### Closure call() Method\n\nThe new `call()` method for closures is used as a shorthand way of invoking a\nclosure whilst binding an object scope to it. This creates more perfomant and\ncompact code by removing the need to create an intermediate closure before\ninvoking it.\n\n```PHP\nclass A {private $x = 1;}\n\n// Pre PHP 7 code\n$getXCB = function() {return $this-\u003ex;};\n$getX = $getXCB-\u003ebindTo(new A, 'A'); // intermediate closure\necho $getX(); // 1\n\n// PHP 7+ code\n$getX = function() {return $this-\u003ex;};\necho $getX-\u003ecall(new A); // 1\n```\n\nRFC: [Closure::call](https://wiki.php.net/rfc/closure_apply)\n\n### Filtered `unserialize()`\n\nThis feature seeks to provide better security when unserializing objects on\nuntrusted data. It prevents possible code injections by enabling the developer\nto whitelist classes that can be unserialized.\n\n```PHP\n// converts all objects into __PHP_Incomplete_Class object\n$data = unserialize($foo, [\"allowed_classes\" =\u003e false]);\n\n// converts all objects into __PHP_Incomplete_Class object except those of MyClass and MyClass2\n$data = unserialize($foo, [\"allowed_classes\" =\u003e [\"MyClass\", \"MyClass2\"]]);\n\n// default behaviour (same as omitting the second argument) that accepts all classes\n$data = unserialize($foo, [\"allowed_classes\" =\u003e true]);\n```\n\nRFC: [Filtered unserialize()](https://wiki.php.net/rfc/secure_unserialize)\n\n### `IntlChar` Class\n\nThe new `IntlChar` class seeks to expose additional ICU functionality. The\nclass itself defines a number of static methods and constants that can be used\nto manipulate unicode characters.\n\n```PHP\nprintf('%x', IntlChar::CODEPOINT_MAX); // 10ffff\necho IntlChar::charName('@'); // COMMERCIAL AT\nvar_dump(IntlChar::ispunct('!')); // bool(true)\n```\n\nIn order to use this class, the `Intl` extension must be installed.\n\n**BC Breaks**\n - Classes in the global namespace must not be called `IntlChar`.\n\nRFC: [IntlChar class](https://wiki.php.net/rfc/intl.char)\n\n### Expectations\n\nExpectations are backwards compatible enhancement to the older `assert()`\nfunction. They enable for zero-cost assertions in production code, and provide\nthe ability to throw custom exceptions on error.\n\nThe `assert()` function's prototype is as follows:\n```\nvoid assert (mixed $expression [, mixed $message]);\n```\n\nAs with the old API, if `$expression` is a string, then it will be evaluated.\nIf the first argument is falsy, then the assertion fails. The second argument\ncan either be a plain string (causing an AssertionError to be triggered),\nor a custom exception object containing an error message.\n\n```PHP\nini_set('assert.exception', 1);\n\nclass CustomError extends AssertionError {}\n\nassert(false, new CustomError('Some error message'));\n```\n\nWith this feature comes two PHP.ini settings (along with their default values):\n - zend.assertions = 1\n - assert.exception = 0\n\n**zend.assertions** has three values:\n - **1** = generate and execute code (development mode)\n - **0** = generate code and jump around at it at runtime\n - **-1** = don't generate any code (zero-cost, production mode)\n\n**assert.exception** means that an exception is thrown when an assertion fails.\nThis is switched off by default to remain compatible with the old `assert()`\nfunction.\n\nRFC: [Expectations](https://wiki.php.net/rfc/expectations)\n\n### Group `use` Declarations\n\nThis gives the ability to group multiple `use` declarations according to the\nparent namespace. This seeks to remove code verbosity when importing multiple\nclasses, functions, or constants that come under the same namespace.\n\n```PHP\n// Pre PHP 7 code\nuse some\\namespace\\ClassA;\nuse some\\namespace\\ClassB;\nuse some\\namespace\\ClassC as C;\n\nuse function some\\namespace\\fn_a;\nuse function some\\namespace\\fn_b;\nuse function some\\namespace\\fn_c;\n\nuse const some\\namespace\\ConstA;\nuse const some\\namespace\\ConstB;\nuse const some\\namespace\\ConstC;\n\n// PHP 7+ code\nuse some\\namespace\\{ClassA, ClassB, ClassC as C};\nuse function some\\namespace\\{fn_a, fn_b, fn_c};\nuse const some\\namespace\\{ConstA, ConstB, ConstC};\n```\n\nRFC: [Group use Declarations](https://wiki.php.net/rfc/group_use_declarations)\n\n### Generator Return Expressions\n\nThis feature builds upon the generator functionality introduced into PHP 5.5.\nIt enables for a `return` statement to be used within a generator to enable for\na final *expression* to be returned (return by reference is not allowed). This\nvalue can be fetched using the new `Generator::getReturn()` method, which may\nonly be used once the generator has finishing yielding values.\n\n```PHP\n// IIFE syntax now possible - see the Uniform Variable Syntax subsection in the Changes section\n$gen = (function() {\n    yield 1;\n    yield 2;\n\n    return 3;\n})();\n\nforeach ($gen as $val) {\n    echo $val, PHP_EOL;\n}\n\necho $gen-\u003egetReturn(), PHP_EOL;\n\n// output:\n// 1\n// 2\n// 3\n```\n\nBeing able to explicitly return a final value from a generator is a handy\nability to have. This is because it enables for a final value to be returned by\na generator (from perhaps some form of coroutine computation) that can be\nspecifically handled by the client code executing the generator. This is far\nsimpler than forcing the client code to firstly check whether the final value\nhas been yielded, and then if so, to handle that value specifically.\n\nRFC: [Generator Return Expressions](https://wiki.php.net/rfc/generator-return-expressions)\n\n### Generator Delegation\n\nGenerator delegation builds upon the ability of being able to return\nexpressions from generators. It does this by using an new syntax of `yield from\n\u003cexpr\u003e`, where \u003cexpr\u003e can be any `Traversable` object or array. This \u003cexpr\u003e\nwill be advanced until no longer valid, and then execution will continue in the\ncalling generator. This feature enables `yield` statements to be broken down\ninto smaller operations, thereby promoting cleaner code that has greater\nreusability.\n\n```PHP\nfunction gen()\n{\n    yield 1;\n    yield 2;\n\n    return yield from gen2();\n}\n\nfunction gen2()\n{\n    yield 3;\n\n    return 4;\n}\n\n$gen = gen();\n\nforeach ($gen as $val)\n{\n    echo $val, PHP_EOL;\n}\n\necho $gen-\u003egetReturn();\n\n// output\n// 1\n// 2\n// 3\n// 4\n```\n\nRFC: [Generator Delegation](https://wiki.php.net/rfc/generator-delegation)\n\n### Integer Division with `intdiv()`\n\nThe `intdiv()` function has been introduced to handle division where an integer is to be returned.\n\n```PHP\nvar_dump(intdiv(10, 3)); // int(3)\n```\n\n**BC Breaks**\n - Functions in the global namespace must not be called `intdiv`.\n\nRFC: [intdiv()](https://wiki.php.net/rfc/intdiv)\n\n### `session_start()` Options\n\nThis feature gives the ability to pass in an array of options to the\n`session_start()` function. This is used to set session-based php.ini options:\n\n```PHP\nsession_start(['cache_limiter' =\u003e 'private']); // sets the session.cache_limiter option to private\n```\n\nThis feature also introduces a new php.ini setting (`session.lazy_write`) that\nis, by default, set to true and means that session data is only rewritten if it\nchanges.\n\nRFC: [Introduce session_start() Options](https://wiki.php.net/rfc/session-lock-ini)\n\n### `preg_replace_callback_array()` Function\n\nThis new function enables code to be written more cleanly when using the\n`preg_replace_callback()` function. Prior to PHP 7, callbacks that needed to be\nexecuted per regular expression required the callback function (second\nparameter of `preg_replace_callback()`) to be polluted with lots of branching\n(a hacky method at best).\n\nNow, callbacks can be registered to each regular expression using an associative\narray, where the key is a regular expression and the value is a callback.\n\nFunction Signature:\n```\nstring preg_replace_callback_array(array $regexesAndCallbacks, string $input);\n```\n\n```PHP\n$tokenStream = []; // [tokenName, lexeme] pairs\n\n$input = \u003c\u003c\u003c'end'\n$a = 3; // variable initialisation\nend;\n\n// Pre PHP 7 code\npreg_replace_callback(\n    [\n        '~\\$[a-z_][a-z\\d_]*~i',\n        '~=~',\n        '~[\\d]+~',\n        '~;~',\n        '~//.*~'\n    ],\n    function ($match) use (\u0026$tokenStream) {\n        if (strpos($match[0], '$') === 0) {\n            $tokenStream[] = ['T_VARIABLE', $match[0]];\n        } elseif (strpos($match[0], '=') === 0) {\n            $tokenStream[] = ['T_ASSIGN', $match[0]];\n        } elseif (ctype_digit($match[0])) {\n            $tokenStream[] = ['T_NUM', $match[0]];\n        } elseif (strpos($match[0], ';') === 0) {\n            $tokenStream[] = ['T_TERMINATE_STMT', $match[0]];\n        } elseif (strpos($match[0], '//') === 0) {\n            $tokenStream[] = ['T_COMMENT', $match[0]];\n        }\n    },\n    $input\n);\n\n// PHP 7+ code\npreg_replace_callback_array(\n    [\n        '~\\$[a-z_][a-z\\d_]*~i' =\u003e function ($match) use (\u0026$tokenStream) {\n            $tokenStream[] = ['T_VARIABLE', $match[0]];\n        },\n        '~=~' =\u003e function ($match) use (\u0026$tokenStream) {\n            $tokenStream[] = ['T_ASSIGN', $match[0]];\n        },\n        '~[\\d]+~' =\u003e function ($match) use (\u0026$tokenStream) {\n            $tokenStream[] = ['T_NUM', $match[0]];\n        },\n        '~;~' =\u003e function ($match) use (\u0026$tokenStream) {\n            $tokenStream[] = ['T_TERMINATE_STMT', $match[0]];\n        },\n        '~//.*~' =\u003e function ($match) use (\u0026$tokenStream) {\n            $tokenStream[] = ['T_COMMENT', $match[0]];\n        }\n    ],\n    $input\n);\n```\n\n**BC Breaks**\n - Functions in the global namespace must not be called `preg_replace_callback_array`.\n\nRFC: [Add preg_replace_callback_array Function](https://wiki.php.net/rfc/preg_replace_callback_array)\n\n### CSPRNG Functions\n\nThis feature introduces two new functions for generating cryptographically\nsecure integers and strings. They expose simple APIs and are\nplatform-independent.\n\nFunction signatures:\n```\nstring random_bytes(int length);\nint random_int(int min, int max);\n```\n\nBoth functions will emit an `Error` exception if a source of sufficient\nrandomness cannot be found.\n\n**BC Breaks**\n - Functions in the global namespace must not be called `random_int` or `random_bytes`.\n\nRFC: [Easy User-land CSPRNG](https://wiki.php.net/rfc/easy_userland_csprng)\n\n### Support for Array Constants in `define()`\n\nThe ability to define array constants was introduced in PHP 5.6 using the\n`const` keyword. This ability has now been applied to the `define()` function\ntoo:\n\n```PHP\ndefine('ALLOWED_IMAGE_EXTENSIONS', ['jpg', 'jpeg', 'gif', 'png']);\n```\n\nRFC: no RFC available\n\n### Reflection Additions\n\nTwo new reflection classes have been introduced in PHP 7. The first is\n`ReflectionGenerator`, which is used for introspection on generators:\n\n```PHP\nclass ReflectionGenerator\n{\n    public __construct(Generator $gen)\n    public array getTrace($options = DEBUG_BACKTRACE_PROVIDE_OBJECT)\n    public int getExecutingLine(void)\n    public string getExecutingFile(void)\n    public ReflectionFunctionAbstract getFunction(void)\n    public Object getThis(void)\n    public Generator getExecutingGenerator(void)\n}\n```\n\nThe second is `ReflectionType` to better support the scalar and return type\ndeclaration features:\n\n```PHP\nclass ReflectionType\n{\n    public bool allowsNull(void)\n    public bool isBuiltin(void)\n    public string __toString(void)\n}\n```\n\nAlso, two new methods have been introduced into `ReflectionParameter`:\n```PHP\nclass ReflectionParameter\n{\n    // ...\n    public bool hasType(void)\n    public ReflectionType getType(void)\n}\n```\n\nAs well as two new methods in `ReflectionFunctionAbstract`:\n```PHP\nclass ReflectionFunctionAbstract\n{\n    // ...\n    public bool hasReturnType(void)\n    public ReflectionType getReturnType(void)\n}\n```\n\n**BC Breaks**\n - Classes in the global namespace must not be called `ReflectionGenerator` or\n   `ReflectionType`.\n\nRFC: no RFC available\n\n## Changes\n\n### Loosening Reserved Word Restrictions\n\nGlobally reserved words as property, constant, and method names within classes,\ninterfaces, and traits are now allowed. This reduces the surface of BC breaks\nwhen new keywords are introduced and avoids naming restrictions on APIs.\n\nThis is particularly useful when creating internal DSLs with fluent interfaces:\n```PHP\n// 'new', 'private', and 'for' were previously unusable\nProject::new('Project Name')-\u003eprivate()-\u003efor('purpose here')-\u003ewith('username here');\n```\n\nThe only limitation is that the `class` keyword still cannot be used as a\nconstant name, otherwise it would conflict with the class name resolution\nsyntax (`ClassName::class`).\n\nRFC: [Context Sensitive Lexer](https://wiki.php.net/rfc/context_sensitive_lexer)\n\n### Uniform Variable Syntax\n\nThis change brings far greater orthogonality to the variable operators in PHP.\nIt enables for a number of new combinations of operators that were previously\ndisallowed, and so introduces new ways to achieve old operations in terser\ncode.\n\n```PHP\n// nesting ::\n$foo::$bar::$baz // access the property $baz of the $foo::$bar property\n\n// nesting ()\nfoo()() // invoke the return of foo()\n\n// operators on expressions enclosed in ()\n(function () {})() // IIFE syntax from JS\n```\n\nThe ability to arbitrarily combine variable operators came from reversing the\nevaluation semantics of indirect variable, property, and method references. The\nnew behaviour is more intuitive and always follows a left-to-right evaluation\norder:\n\n```PHP\n                        // old meaning            // new meaning\n$$foo['bar']['baz']     ${$foo['bar']['baz']}     ($$foo)['bar']['baz']\n$foo-\u003e$bar['baz']       $foo-\u003e{$bar['baz']}       ($foo-\u003e$bar)['baz']\n$foo-\u003e$bar['baz']()     $foo-\u003e{$bar['baz']}()     ($foo-\u003e$bar)['baz']()\nFoo::$bar['baz']()      Foo::{$bar['baz']}()      (Foo::$bar)['baz']()\n```\n\n**BC Breaks**\n - Code that relied upon the old evaluation order must be rewritten to\n   explicitly use that evaluation order with curly braces (see middle column of\nthe above). This will make the code both forwards compatible with PHP 7.x and\nbackwards compatible with PHP 5.x\n\nRFC: [Uniform Variable Syntax](https://wiki.php.net/rfc/uniform_variable_syntax)\n\n### Exceptions in the Engine\n\nExceptions in the engine converts many fatal and recoverable fatal errors into\nexceptions. This enables for graceful degradation of applications through\ncustom error handling procedures. It also means that cleanup-driven features\nsuch as the `finally` clause and object destructors will now be executed.\nFurthermore, by using exceptions for application errors, stack traces will be\nproduced for additional debugging information.\n\n```PHP\nfunction sum(float ...$numbers) : float\n{\n    return array_sum($numbers);\n}\n\ntry {\n    $total = sum(3, 4, null);\n} catch (TypeError $typeErr) {\n    // handle type error here\n}\n```\n\nThe new exception hierarchy is as follows:\n```\ninterface Throwable\n    |- Exception implements Throwable\n        |- ...\n    |- Error implements Throwable\n        |- TypeError extends Error\n        |- ParseError extends Error\n        |- AssertionError extends Error\n        |- ArithmeticError extends Error\n            |- DivisionByZeroError extends ArithmeticError\n```\n\nSee the [Throwable Interface](#throwable-interface) subsection in the Changes\nsection for more information on this new exception hierarchy.\n\n**BC Breaks**\n - Custom error handlers used for handling (and typically ignoring) recoverable\n   fatal errors will not longer work since exceptions will now be thrown\n - Parse errors occurring in `eval()`ed code will now become exceptions,\n   requiring them to be wrapped in a `try...catch` block\n\nRFC: [Exceptions in the Engine](https://wiki.php.net/rfc/engine_exceptions_for_php7)\n\n### Throwable Interface\n\nThis change affects PHP's exception hierarchy due to the introduction of\n[exceptions in the engine](#exceptions-in-the-engine). Rather than placing\nfatal and recoverable fatal errors under the pre-existing `Exception` class\nhierarchy, [it was\ndecided](https://wiki.php.net/rfc/engine_exceptions_for_php7#doodle__form__introduce_and_use_baseexception)\nto implement a new hierarchy of exceptions to prevent PHP 5.x code from\ncatching these new exceptions with catch-all (`catch (Exception $e)`) clauses.\n\nThe new exception hierarchy is as follows:\n```\ninterface Throwable\n    |- Exception implements Throwable\n        |- ...\n    |- Error implements Throwable\n        |- TypeError extends Error\n        |- ParseError extends Error\n        |- AssertionError extends Error\n        |- ArithmeticError extends Error\n            |- DivisionByZeroError extends ArithmeticError\n```\n\nThe `Throwable` interface is implemented by both `Exception` and `Error` base\nclass hierarchies and defines the following contract:\n```\ninterface Throwable\n{\n    final public string getMessage ( void )\n    final public mixed getCode ( void )\n    final public string getFile ( void )\n    final public int getLine ( void )\n    final public array getTrace ( void )\n    final public string getTraceAsString ( void )\n    public string __toString ( void )\n}\n```\n\n`Throwable` cannot be implemented by user-defined classes - instead, a custom\nexception class should extend one of the pre-existing exceptions classes in\nPHP.\n\nRFC: [Throwable Interface](https://wiki.php.net/rfc/throwable-interface)\n\n### Integer Semantics\n\nThe semantics for some integer-based behaviour has changed in an effort to make\nthem more intuitive and platform-independent. Here is a list of those changes:\n - Casting `NAN` and `INF` to an integer will always result in 0\n - Bitwise shifting by a negative number of bits is now disallowed (causes a\n   bool(false) return and emits an E_WARNING)\n - Left bitwise shifts by a number of bits beyond the bit width of an integer will always result in 0\n - Right bitwise shifts by a number of bits beyond the bit width of an integer\n   will always result in 0 or -1 (sign dependent)\n\n**BC Breaks**\n - Any reliance on the old semantics for the above will no longer work\n\nRFC: [Integer Semantics](https://wiki.php.net/rfc/integer_semantics)\n\n### JSON Extension Replaced with JSOND\n\nThe licensing of the old JSON extension was regarded as non-free, causing\nissues for many Linux-based distributions. The extension has since been\nreplaced with JSOND and comes with some [performance\ngains](https://github.com/bukka/php-jsond-bench/blob/master/reports/0001/summary.md)\nand backward compatibility breakages.\n\n**BC Breaks**\n - A number *must not* end in a decimal point (i.e. `34.` must be changed to either `34.0` or just `34`)\n - The `e` exponent *must not* immediately follow the decimal point (i.e.\n   `3.e3` must be changed to either `3.0e3` or just `3e3`)\n\nRFC: [Replace current json extension with jsond](https://wiki.php.net/rfc/jsond)\n\n### ZPP Failure on Overflow\n\nCoercion between floats to integers can occur when a float is passed to an\ninternal function expecting an integer. If the float is too large to represent\nas an integer, then the value will be silently truncated (which may result in a\nloss of magnitude and sign). This can introduce hard-to-find bugs. This change\ntherefore seeks to notify the developer when an implicit conversion from a\nfloat to an integer has occurred and failed by returning `null` and emitting an\nE_WARNING.\n\n**BC Breaks**\n - Code that once silently worked will now emit an E_WARNING and may fail if\n   the result of the function invocation is directly passed to another function\n(since `null` will now be passed in).\n\nRFC: [ZPP Failure on Overflow](https://wiki.php.net/rfc/zpp_fail_on_overflow)\n\n### Fixes to `foreach()`'s Behaviour\n\nPHP's `foreach()` loop had a number of strange edge-cases to it. These were all\nimplementation-driven and caused a lot of undefined and inconsistent behaviour\nwhen iterating between copies and references of an array, when using iterator\nmanipulators like `current()` and `reset()`, when modifying the array currently\nbeing iterated, and so on.\n\nThis change eliminates the undefined behaviour of these edge-cases and makes\nthe semantics more predictable and intuitive.\n\n`foreach()` by value on arrays\n```PHP\n$array = [1,2,3];\n$array2 = \u0026$array;\n\nforeach($array as $val) {\n    unset($array[1]); // modify array being iterated over\n    echo \"{$val} - \", current($array), PHP_EOL;\n}\n\n// Pre PHP 7 result\n1 - 3\n3 -\n\n// PHP 7+ result\n1 - 1\n2 - 1\n3 - 1\n```\n\nWhen by-value semantics are used, the array being iterated over is now not\nmodified in-place. `current()` also now has defined behaviour, where it will\nalways begin at the start of the array.\n\n`foreach()` by reference on arrays and objects and by value on objects\n```PHP\n$array = [1,2,3];\n\nforeach($array as \u0026$val) {\n    echo \"{$val} - \", current($array), PHP_EOL;\n}\n\n// Pre PHP 7 result\n1 - 2\n2 - 3\n3 -\n\n// PHP 7+ result\n1 - 1\n2 - 1\n3 - 1\n```\n\nThe `current()` function is no longer affected by `foreach()`'s iteration on\nthe array. Also, nested `foreach()`'s using by-reference semantics work\nindependently from each other now:\n```PHP\n$array = [1,2,3];\n\nforeach($array as \u0026$val) {\n    echo $val, PHP_EOL;\n\n    foreach ($array as \u0026$val2) {\n        unset($array[1]);\n        echo $val, PHP_EOL;\n    }\n}\n\n// Pre PHP 7 result\n1\n1\n1\n\n// PHP 7+ result\n1\n1\n1\n3\n3\n3\n```\n\n**BC Breaks**\n - Any reliance on the old (quirky and undocumented) semantics will no longer work.\n\nRFC: [Fix \"foreach\" behavior](https://wiki.php.net/rfc/php7_foreach)\n\n### Changes to `list()`'s Behaviour\n\nThe `list()` function was documented as not supporting strings, however in few cases strings could have been used:\n```PHP\n// array dereferencing\n$str[0] = 'ab';\nlist($a, $b) = $str[0];\necho $a; // a\necho $b; // b\n\n// object dereferencing\n$obj = new StdClass();\n$obj-\u003eprop = 'ab';\nlist($a, $b) = $obj-\u003eprop;\necho $a; // a\necho $b; // b\n\n// function return\nfunction func()\n{\n    return 'ab';\n}\n\nlist($a, $b) = func();\nvar_dump($a, $b);\necho $a; // a\necho $b; // b\n```\n\nThis has now been changed making string usage with `list()` forbidden in all cases.\n\nAlso, empty `list()`'s are now a fatal error, and the order of assigning variables has been changed to left-to-right:\n```PHP\n$a = [1, 2];\nlist($a, $b) = $a;\n\n// OLD: $a = 1, $b = 2\n// NEW: $a = 1, $b = null + \"Undefined index 1\"\n\n$b = [1, 2];\nlist($a, $b) = $b;\n\n// OLD: $a = null + \"Undefined index 0\", $b = 2\n// NEW: $a = 1, $b = 2\n```\n\n**BC Breaks**\n - Making `list()` equal to any non-direct string value is no longer possible.\n   `null` will now be the value for the variable `$a` and `$b` in the above\nexamples\n - Invoking `list()` without any variables will cause a fatal error\n - Reliance upon the old right-to-left assignment order will no longer work\n\nRFC: [Fix list() behavior inconsistency](https://wiki.php.net/rfc/fix_list_behavior_inconsistency)\n\nRFC: [Abstract syntax tree](https://wiki.php.net/rfc/abstract_syntax_tree)\n\n### Changes to Division by Zero Semantics\n\nPrior to PHP 7, when a divisor was 0 for either the divide (/) or modulus (%) operators,\nan E_WARNING would be emitted and `false` would be returned. This was nonsensical for\nan arithmetic operation to return a boolean in some cases, and so the behaviour has been\nrectified in PHP 7.\n\nThe new behaviour causes the divide operator to return a float as either +INF, -INF, or\nNAN. The modulus operator E_WARNING has been removed and (alongside the new `intdiv()`\nfunction) will throw a `DivisionByZeroError` exception. In addition, the `intdiv()`\nfunction may also throw an `ArithmeticError` when valid integer arguments are supplied\nthat cause an incorrect result (due to integer overflow).\n\n```PHP\nvar_dump(3/0); // float(INF) + E_WARNING\nvar_dump(0/0); // float(NAN) + E_WARNING\n\nvar_dump(0%0); // DivisionByZeroError\n\nintdiv(PHP_INT_MIN, -1); // ArithmeticError\n```\n\n**BC Breaks**\n - The divide operator will no longer return `false` (which could have been silently coerced\n to 0 in an arithmetic operation)\n - The modulus operator will now throw an exception with a 0 divisor instead of returning `false`\n\nRFC: No RFC available\n\n### Fixes to Custom Session Handler Return Values\n\nWhen implementing custom session handlers, predicate functions from the\n`SessionHandlerInterface` that expect a `true` or `false` return value did not\nbehave as expected. Due to an error in the previous implementation, only a `-1`\nreturn value was considered false - meaning that even if the boolean\n`false` was used to denote a failure, it was taken as a success:\n```PHP\n\u003c?php\n\nclass FileSessionHandler implements SessionHandlerInterface\n{\n    private $savePath;\n\n    function open($savePath, $sessionName)\n    {\n        return false; // always fail\n    }\n\n    function close(){return true;}\n\n    function read($id){}\n\n    function write($id, $data){}\n\n    function destroy($id){}\n\n    function gc($maxlifetime){}\n}\n\nsession_set_save_handler(new FileSessionHandler());\n\nsession_start(); // doesn't cause an error in pre PHP 7 code\n```\n\nNow, the above will fail with a fatal error. Having a `-1` return value will\nalso continue to fail, whilst `0` and `true` will continue to mean success. Any\nother value returned will now cause a failure and emit an E_WARNING.\n\n**BC Breaks**\n - If boolean `false` is returned, it will actually fail now\n - If anything other than a boolean, `0`, or `-1` is returned, it will fail and cause a warning to be emitted\n\nRFC: [Fix handling of custom session handler return values](https://wiki.php.net/rfc/session.user.return-value)\n\n### Deprecation of PHP 4-Style Constructors\n\nPHP 4 constructors were preserved in PHP 5 alongside the new `__construct()`.\nNow, PHP 4-style constructors are being deprecated in favour of having only a\nsingle method (`__construct()`) to be invoked on object creation. This is\nbecause the conditions upon whether the PHP 4-style constructor was invoked\ncaused additional cognitive overhead to developers that could also be confusing\nto the inexperienced.\n\nFor example, if the class is defined within a namespace or if an\n`__construct()` method existed, then a PHP 4-style constructor was recognised\nas a plain method. If it was defined above an `__construct()` method, then an\nE_STRICT notice would be emitted, but still recognised as a plain method.\n\nNow in PHP 7, if the class is not in a namespace and there is no\n`__construct()` method present, the PHP 4-style constructor will be used as a\nconstructor but an E_DEPRECATED will be emitted. In PHP 8, the PHP 4-style\nconstructor will always be recognised as a plain method and the E_DEPRECATED\nnotice will disappear.\n\n**BC Breaks**\n - Custom error handlers may be affected by the raising of E_DEPRECATED\n   warnings. To fix this, simply update the class constructor name to\n`__construct`.\n\nRFC: [Remove PHP 4 Constructors](https://wiki.php.net/rfc/remove_php4_constructors)\n\n### Removal of date.timezone Warning\n\nWhen any date- or time-based functions were invoked and a default timezone had\nnot been set, a warning was emitted. The fix was to simply set the\n`date.timezone` INI setting to a valid timezone, but this forced users to have\na php.ini file and to configure it beforehand. Since this was the only setting\nthat had a warning attached to it, and it defaulted to UTC anyway, the warning\nhas now been removed.\n\nRFC: [Remove the date.timezone warning](https://wiki.php.net/rfc/date.timezone_warning_removal)\n\n### Removal of Alternative PHP Tags\n\nThe alternative PHP tags `\u003c%` (and `\u003c%=`), `%\u003e`, `\u003cscript language=\"php\"\u003e`, and\n`\u003c/script\u003e` have now been removed.\n\n**BC Breaks**\n - Code that relied upon these alternative tags needs to be updated to either\n   the normal or short opening and closing tags. This can either be done\n   manually or automated with [this porting script](https://gist.github.com/nikic/74769d74dad8b9ef221b).\n\nRFC: [Remove alternative PHP tags](https://wiki.php.net/rfc/remove_alternative_php_tags)\n\n### Removal of Multiple Default Blocks in Switch Statements\n\nPreviously, it was possible to specify multiple `default` block statements\nwithin a switch statement (where the last `default` block was only executed).\nThis (useless) ability has now been removed and causes a fatal error.\n\n**BC Breaks**\n - Any code written (or more likely generated) that created switch statements\n   with multiple `default` blocks will now become a fatal error.\n\nRFC: [Make defining multiple default cases in a switch a syntax error](https://wiki.php.net/rfc/switch.default.multiple)\n\n### Removal of Redefinition of Parameters with Duplicate Names\n\nPreviously, it was possible to specify parameters with duplicate names within a function definition.\nThis ability has now been removed and causes a fatal error.\n\n```PHP\nfunction foo($version, $version)\n{\n    return $version;\n}\n\necho foo(5, 7);\n\n// Pre PHP 7 result\n7\n\n// PHP 7+ result\nFatal error: Redefinition of parameter $version in /redefinition-of-parameters.php\n```\n\n**BC Breaks**\n - Function parameters with duplicate name will now become a fatal error.\n\n### Removal of Dead Server APIs\n\nThe following SAPIs have been removed from the core (most of which have been moved to PECL):\n- sapi/aolserver\n- sapi/apache\n- sapi/apache_hooks\n- sapi/apache2filter\n- sapi/caudium\n- sapi/continuity\n- sapi/isapi\n- sapi/milter\n- sapi/nsapi\n- sapi/phttpd\n- sapi/pi3web\n- sapi/roxen\n- sapi/thttpd\n- sapi/tux\n- sapi/webjames\n- ext/mssql\n- ext/mysql\n- ext/sybase_ct\n- ext/ereg\n\nRFC: [Removal of dead or not yet PHP7 ported SAPIs and extensions](https://wiki.php.net/rfc/removal_of_dead_sapis_and_exts)\n\n### Removal of Hex Support in Numerical Strings\n\nA Stringy hexadecimal number is no longer recognised as numerical.\n```PHP\nvar_dump(is_numeric('0x123'));\nvar_dump('0x123' == '291');\necho '0x123' + '0x123';\n\n// Pre PHP 7 result\nbool(true)\nbool(true)\n582\n\n// PHP 7+ result\nbool(false)\nbool(false)\n0\n```\n\nThe reason for this change is to promote better consistency between the\nhandling of stringy hex numbers across the language. For example, explicit\ncasts do not recognise stringy hex numbers:\n```PHP\nvar_dump((int) '0x123'); // int(0)\n```\n\nInstead, stringy hex numbers should be validated and converted using the `filter_var()` function:\n```PHP\nvar_dump(filter_var('0x123', FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX)); // int(291)\n```\n\n**BC Breaks**\n - This change affects the `is_numeric()` function and various operators, including `==`, `+`, `-`, `*`, `/`, `%`, `**`, `++`, and `--`\n\nRFC: [Remove hex support in numeric strings](https://wiki.php.net/rfc/remove_hex_support_in_numeric_strings)\n\n### Removal of Deprecated Functionality\n\nAll Deprecated functionality has been removed, most notably:\n - The original mysql extension (ext/mysql)\n - The ereg extension (ext/ereg)\n - Assigning `new` by reference\n - Scoped calls of non-static methods from an incompatible `$this` context\n   (such as `Foo::bar()` from outside a class, where `bar()` is not a static\nmethod)\n\n**BC Breaks**\n - Any code that ran with deprecation warnings in PHP 5 will no longer work (you were warned!)\n\nRFC: [Remove deprecated functionality in PHP 7](https://wiki.php.net/rfc/remove_deprecated_functionality_in_php7)\n\n### Reclassification and Removal of E_STRICT Notices\n\nE_STRICT notices have always been a bit of a grey area in their meaning. This\nchanges removes this error category altogether and either: removes the E_STRICT\nnotice, changes it to an E_DEPRECATED if the functionality will be removed in\nfuture, changes it to an E_NOTICE, or promotes it to an E_WARNING.\n\n**BC Breaks**\n - Because E_STRICT is in the lowest severity error category, any error\n   promotions to an E_WARNING may break custom error handlers\n\nRFC: [Reclassify E_STRICT notices](https://wiki.php.net/rfc/reclassify_e_strict)\n\n### Deprecation of Salt Option for `password_hash()`\n\nWith the introduction of the new password hashing API in PHP 5.5, many began\nimplementing it and generating their own salts. Unfortunately, many of these\nsalts were generated from cryptographically insecure functions like mt_rand(),\nmaking the salt far weaker than what would have been generated by default.\n(Yes, a salt is always used when hashing passwords with this new API!) The option to\ngenerate salts have therefore been deprecated to prevent developers from\ncreating insecure salts.\n\nRFC: no RFC available\n\n### Error on Invalid Octal Literals\n\nInvalid octal literals will now cause a parse error rather than being\ntruncated and silently ignored.\n\n```PHP\necho 0678; // Parse error:  Invalid numeric literal in...\n```\n\n**BC Breaks**\n - Any invalid octal literals in code will now cause parse errors\n\nRFC: no RFC available\n\n### `substr()` Return Value Change\n\n`substr()` will now return an empty string instead of `false` when the start\nposition of the truncation is equal to the string length:\n```PHP\nvar_dump(substr('a', 1));\n\n// Pre PHP 7 result\nbool(false)\n\n// PHP 7+ result\nstring(0) \"\"\n```\n\n`substr()` may still return `false` in other cases, however.\n\n**BC Breaks**\n - Code that strictly checked for a `bool(false)` return value may now be\n semantically invalid\n\nRFC: no RFC available\n\n## FAQ\n\n### What happened to PHP 6?\n\nPHP 6 was the major PHP version that never came to light. It was supposed to\nfeature full support for Unicode in the core, but this effort was too ambitious\nwith too many complications arising. The predominant reasons why version 6 was\nskipped for this new major version are as follows:\n - **To prevent confusion**. Many resources were written about PHP 6 and much\n   of the community knew what was featured in it. PHP 7 is a completely\ndifferent beast with entirely different focuses (specifically on performance)\nand entirely different feature sets. Thus, a version has been skipped to\nprevent any confusion or misconceptions surrounding what PHP 7 is.\n - **To let sleeping dogs lie**. PHP 6 was seen as a failure and a large amount\n   of PHP 6 code still remains in the PHP repository. It was therefore seen as\nbest to move past version 6 and start afresh on the next major version, version\n7.\n\nRFC: [Name of Next Release of PHP](https://wiki.php.net/rfc/php6)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftpunt%2Fphp7-reference","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftpunt%2Fphp7-reference","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftpunt%2Fphp7-reference/lists"}