Evolution of PHP — v5.6 to v8.0

You can only implement Throwable through Error and Exception.

Unicode Codepoint Escape Syntax — “u{xxxxx}”echo "u{202E}Reversed text"; // outputs ‮Reversed textecho "mañana"; // "mau{00F1}ana"echo "mañana"; // "manu{0303}ana" "n" with combining ~ character (U+0303)Context Sensitive LexerWith this globally reserved words became semi-reserved:callable class trait extends implements static abstract final public protected private constenddeclare endfor endforeach endif endwhile and global goto instanceof insteadof interfacenamespace new or xor try use var exit list clone include include_once throw arrayprint echo require require_once return else elseif default break continue switch yieldfunction if endswitch finally for foreach declare case do while as catch die self parentExcept it’s still forbidden to define a class constant named as class because of the class name resolution ::class.

Generator return expressionsUniform variable syntaxLevel support for the dirname() functionPHP 7.

1Nullable Typesfunction answer(): ?int { return null; //ok}function answer(): ?int { return 42; // ok}function answer(): ?int { return new stdclass(); // error}function say(?string $msg) { if ($msg) { echo $msg; }}say('hello'); // ok — prints hellosay(null); // ok — does not printsay(); // error — missing parametersay(new stdclass); //error — bad typeVoid Returnsfunction should_return_nothing(): void { return 1; // Fatal error: A void function must not return a value}Unlike other return types which are enforced when a function is called, this type is checked at compile-time, which means that an error is produced without the function needing to be called.

A function with a void return type, or void function, may either return implicitly, or have a return statement without a value:function lacks_return(): void { // valid}Iterable pseudo typeIt is common for a function to accept or return either an array or an object implementing Traversable to be used with foreach.

However, because array is a primitive type and Traversable is an interface, there currently is no way to use a type declaration on a parameter or return type to indicate that the value is iterable.

function foo(iterable $iterable) { foreach ($iterable as $value) { // .

}}iterable can also be used as a return type to indicate a function will return an iterable value.

If the returned value is not an array or instance of Traversable, a TypeError will be thrown.

function bar(): iterable { return [1, 2, 3];}Parameters declared as iterable may use null or an array as a default value.

function foo(iterable $iterable = []) { // .

}Closure from callableclass Closure { .

public static function fromCallable(callable $callable) : Closure {.

} .

}Square bracket syntax for array destructuring assignment$array = [1, 2, 3];// Assigns to $a, $b and $c the values of their respective array elements in $array with keys numbered from zero[$a, $b, $c] = $array; // Assigns to $a, $b and $c the values of the array elements in $array with the keys "a", "b" and "c", respectively["a" => $a, "b" => $b, "c" => $c] = $array;Square bracket syntax for list()$powersOfTwo = [1 => 2, 2 => 4, 3 => 8];list(1 => $oneBit, 2 => $twoBit, 3 => $threeBit) = $powersOfTwo;Class constant visibilityclass Token { // Constants default to public const PUBLIC_CONST = 0; // Constants then also can have a defined visibility private const PRIVATE_CONST = 0; protected const PROTECTED_CONST = 0; public const PUBLIC_CONST_TWO = 0; //Constants can only have one visibility declaration list private const FOO = 1, BAR = 2;}Catching Multiple Exception Typestry { // Some code.

} catch (ExceptionType1 | ExceptionType2 $e) { // Code to handle the exception} catch (Exception $e) { // .

}PHP 7.

2Parameter Type Widening<?php class ArrayClass { public function foo(array $foo) { /* .

*/ }} // This RFC proposes allowing the type to be widened to be untyped aka any// type can be passed as the parameter.

// Any type restrictions can be done via user code in the method body.

class EverythingClass extends ArrayClass { public function foo($foo) { /* .

*/ }}Counting of non-countable objectsCalling count() on a scalar or object that doesn't implement the Countable interface (http://php.

net/manual/en/class.

countable.

php) returns 1 (illogical).

In this version added a warning when calling count() with a parameter that is a scalar, null, or an object that doesn't implement Countable.

Trailing Commas In List Syntax in namespace usesuse FooBar{ Foo, Bar, Baz, };Argon2 Password HashThe existing password_* functions provided a forward compatible, simplified interface for hashing passwords.

This RFC proposes the implementation of Argon2i (v1.

3) within the password_* functions for use as a secure alternative to Bcrypt.

Debugging PDO Prepared Statement Emulation$db = new PDO(.

); // works with statements without bound values$stmt = $db->query('SELECT 1');var_dump($stmt->activeQueryString()); // => string(8) "SELECT 1" $stmt = $db->prepare('SELECT :string');$stmt->bindValue(':string', 'foo'); // returns unparsed query before executionvar_dump($stmt->activeQueryString()); // => string(14) "SELECT :string" // returns parsed query after execution$stmt->execute();var_dump($stmt->activeQueryString()); // => string(11) "SELECT 'foo'"PHP 7.

3JSON_THROW_ON_ERRORNot having an adequate way to handle errors when using JSON has been a problem for quite a long time, and web developers all over the world have seen this as a huge downside of the language.

Until PHP v7.

2 we needed to use a workaround to get an error from JSON and it was neither reliable, nor proficient in its job;Here is an example:json_decode("{");json_last_error() === JSON_ERROR_NONE // the result is falsejson_last_error_msg() // The result is "Syntax error"So let’s see how we could employ this new sugar:use JsonException; try { $json = json_encode("{", JSON_THROW_ON_ERROR); return base64_encode($json);} catch (JsonException $e) { throw new EncryptException('Could not encrypt the data.

', 0, $e);}As you can see from the previous code the json_encode function has now an optional parameter JSON_THROW_ON_ERROR — this will catch the error and display it using the following exception methods:$e->getMessage(); // like json_last_error_msg()$e->getCode(); // like json_last_error()Added is_countable function// Before:if (is_array($foo) || $foo instanceof Countable) { // $foo is countable}// Afterif (is_countable($foo)) { // $foo is countable}Added array functions array_key_first(), array_key_last()$firstKey = array_key_first($array);$lastKey = array_key_last($array);Added native “same site” cookie supportThere are now two possibilities for a cookie that is using the samesite flag: “Lax” and “Strict”.

The difference between Lax and Strict is the accessibility of the cookie in requests originating from another registrable domain using the HTTP GET method.

Cookies using Lax will be accessible in a GET request originated from another registrable domain, whereas cookies using Strict will not be accessible in a GET request originated from another registrable domain.

There is no difference with POST methods: the browser should not allow the cookie to be accessed in a POST request originating from another registrable domain.

Set-Cookie: key=value; path=/; domain=example.

org; HttpOnly; SameSite=Lax|StrictMigrated PCRE to PCRE2Argon2 Password Hash EnhancementsThe existing password_* functions provided a forward compatible, simplified interface for hashing passwords.

This RFC proposes the implementation of Argon2id within the password_* functions for use as a secure alternative to the originally proposed Argon2i.

Allow a Trailing Comma in Function Calls$newArray = array_merge( $arrayOne, $arrayTwo, ['foo', 'bar'], // comma is allowed in function calls);list() Reference Assignment$array = [1, 2];list($a, &$b) = $array;This is equivalent to the following:$array = [1, 2];$a = $array[0];$b =& $array[1];Deprecated case-insensitive constantsPHP 7.

4 (In development)Typed propertiesclass User { public int $id; public string $name; public function __construct(int $id, string $name) { $this->id = $id; $this->name = $name; }}Foreign Function InterfaceFFI is one of the features that made Python and LuaJIT very useful for fast prototyping.

It allows calling C functions and using C data types from pure scripting language and therefore develop “system code” more productively.

For PHP, FFI opens a way to write PHP extensions and bindings to C libraries in pure PHP.

Null Coalescing Assignment Operator// The folloving lines are doing the same$this->request->data['comments']['user_id'] = $this->request->data['comments']['user_id'] ??.'value';// Instead of repeating variables with long names, the equal coalesce operator is used$this->request->data['comments']['user_id'] ??= 'value';PreloadingPHP has been using opcode caches for ages (APC, Turck MMCache, Zend OpCache).

They achieve significant performance boost by ALMOST completely eliminating the overhead of PHP code recompilation.

Preloading is going to be controlled by just a single new php.

ini directive — opcache.

preload.

Using this directive we will specify a single PHP file — which will perform the preloading task.

Once loaded, this file is then fully executed — and may preload other files, either by including them or by using the opcache_compile_file() function.

Always available hash extensionThis will make hash extension (`ext/hash`) always available, similar to the `date`.

The hash extension provides a very rich utility with many hashing algorithms which is extremely useful in modern day applications, not only in userland code but also very much in internals.

On the way to PHP 8.

0JIT.

In short.

When you start a PHP program, the Zend Engine will parse the code into an abstract syntax tree (AST) and translate it to opcodes.

The opcodes are execution units for the Zend Virtual Machine (Zend VM).

Opcodes are pretty low-level, so much faster to translate to machine code than the original PHP code.

PHP has an extension named OPcache in core, to cache these opcodes.

“JIT” is a technique that will compile parts of the code at runtime, so that the compiled version can be used instead.

This is one of the last and biggest PHP optimisations strategies still on the table.

PHP engineers are looking forwards to seeing how much this new approach can squeeze out of their applications.

Really keen on seeing this myself.

Consistent type errors for internal functionsMake the internal parameter parsing APIs always generate a TypeError if parameter parsing fails.

It should be noted that this also includes ArgumentCountError (a child of TypeError) for cases where too few/many arguments were passed.

Performance comparisonI have composed a simple test to help easily compare performance of different PHP versions (using Docker).

This would even allow to easily check performance of new PHP versions just by adding new container names.

Running on Macbook pro, 2,5 GHz Intel Core i7.

PHP version : 5.

6.

40————————————–test_math : 1.

101 sec.

test_stringmanipulation : 1.

144 sec.

test_loops : 1.

736 sec.

test_ifelse : 1.

122 sec.

Mem: 429.

4609375 kb Peak mem: 687.

65625 kb————————————–Total time: : 5.

103PHP version : 7.

0.

33————————————–test_math : 0.

344 sec.

test_stringmanipulation : 0.

516 sec.

test_loops : 0.

477 sec.

test_ifelse : 0.

373 sec.

Mem: 421.

0859375 kb Peak mem: 422.

2109375 kb————————————–Total time: : 1.

71PHP version : 7.

1.

28————————————–test_math : 0.

389 sec.

test_stringmanipulation : 0.

514 sec.

test_loops : 0.

501 sec.

test_ifelse : 0.

464 sec.

Mem: 420.

9375 kb Peak mem: 421.

3828125 kb————————————–Total time: : 1.

868PHP version : 7.

2.

17————————————–test_math : 0.

264 sec.

test_stringmanipulation : 0.

391 sec.

test_loops : 0.

182 sec.

test_ifelse : 0.

252 sec.

Mem: 456.

578125 kb Peak mem: 457.

0234375 kb————————————–Total time: : 1.

089PHP version : 7.

3.

4————————————–test_math : 0.

233 sec.

test_stringmanipulation : 0.

317 sec.

test_loops : 0.

171 sec.

test_ifelse : 0.

263 sec.

Mem: 459.

953125 kb Peak mem: 460.

3984375 kb————————————–Total time: : 0.

984PHP version : 7.

4.

0-dev————————————–test_math : 0.

212 sec.

test_stringmanipulation : 0.

358 sec.

test_loops : 0.

205 sec.

test_ifelse : 0.

228 sec.

Mem: 459.

6640625 kb Peak mem: 460.

109375 kb————————————–Total time: : 1.

003If interested in testing yourself, you can find code in repository below.

meskis/php-benchPHP versions benchmarking using Docker.

Contribute to meskis/php-bench development by creating an account on GitHub.

github.

comBenchmarks from PHP 5.

6 and upI really liked visual performance compilation from servebolt.

com of all major versions from 5.

6 and up.

See the results in the tables below.

Performance summaryPHP 7.

0.

0 was a major milestone with significantly improved performance and lower memory usage but PHP maintainers are simply running out of ideas to improve it.

One of the remaining points is JIT (Just in time) compilation.

And it’s coming with PHP 8.

0.

Development directionThroughout PHP versions 7.

x there is a visible path towards more typed (and a bit more objective) and modern programming language.

Still PHP likes to adopt neat and useful features from other programming languages.

Soon we may see some more nice features, like:Named ArgumentsNullsafe CallsEnumerated Types (ENUMs)Arrow functionsWith these in the pipeline, PHP developers would join the pool of modern language adopters.

No language is perfect, but PHP is paving it’s way to the future.

TL;DRTo shorten even more, I have chosen most important changes to my arbitrary opinion given the latest version of PHP 7.

3.

Here they are:Added new null coalesce operatorScalar type declarationsReturn type declarationsThrowable interfaceNullable TypesVoid ReturnsSquare bracket syntax for array destructingClass constant visibilityReferenceshttps://wiki.

php.

net/rfchttps://www.

cloudways.

com/blog/php-5-6-vs-php-7-symfony-benchmarks/https://servebolt.

com/articles/wordpress-5-0-php-7-2-vs-php-7-3-performance-and-speed-benchmark/.. More details

Leave a Reply