Edit

PHP7, Stay up to date !


TL;DR Full changelog http://php.net/ChangeLog-7.php

New features

[7.1] HTTP/2 server push support in ext/curl

Support for server push has been added to the CURL extension (requires version 7.46 and above). This can be leveraged through the curl_multi_setopt() function with the new CURLMOPT_PUSHFUNCTION constant. The constants CURL_PUSH_OK and CURL_PUSH_DENY have also been added so that the execution of the server push callback can either be approved or denied.

$mh = curl_multi_init();
curl_multi_setopt($mh, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
curl_multi_setopt($mh, CURLMOPT_PUSHFUNCTION, $callback);
$callback = function($parent_ch, $pushed_ch, array $headers) {
return CURL_PUSH_OK;
};

[RFC] https://wiki.php.net/rfc/curl_http2_push

[7.1] Asynchronous signal handling

A new function called pcntl_async_signals() has been introduced to enable asynchronous signal handling without using ticks (which introduce a lot of overhead).

pcntl_async_signals(true); // turn on async signals
pcntl_signal(SIGHUP, function($sig) {
echo "SIGHUP\n";
});
posix_kill(posix_getpid(), SIGHUP);

https://github.com/Seldaek/signal-handler

[7.1] Convert callables to Closures with Closure::fromCallable()

class Test
{
public function exposeFunction()
{
return Closure::fromCallable([$this, 'privateFunction']);
}
private function privateFunction($param)
{
var_dump($param);
}
}
$privFunc = (new Test)->exposeFunction();
$privFunc('some value');

[7.1] 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.

var_dump("abcdef"[-2]);
var_dump(strpos("aabbcc", "b", -3));
$string = 'bar';
echo "The last character of '$string' is '$string[-1]'.\n";
string (1) "e"
int(3)
The last character of 'bar' is 'r'.

[7.1] Support for keys in list()

$data = [
["id" => 1, "name" => 'Tom'],
["id" => 2, "name" => 'Fred'],
];
// list() style
list("id" => $id1, "name" => $name1) = $data[0];
// [] style
["id" => $id1, "name" => $name1] = $data[0];
// list() style
foreach ($data as list("id" => $id, "name" => $name)) {
// logic here with $id and $name
}
// [] style
foreach ($data as ["id" => $id, "name" => $name]) {
// logic here with $id and $name
}

[7.1] Multi catch exception handling

try {
// some code
} catch (FirstException | SecondException $e) {
// handle first and second exceptions
}

[7.1] Iterable pseudo-type

function iterator(iterable $iter)
{
foreach ($iter as $val) {
//
}
}

[7.1] Class constant visibility

class ConstDemo
{
const PUBLIC_CONST_A = 1;
public const PUBLIC_CONST_B = 2;
protected const PROTECTED_CONST = 3;
private const PRIVATE_CONST = 4;
}

[7.1] Void functions

function swap(&$left, &$right) : void
{
if ($left === $right) {
return;
}
$tmp = $left;
$left = $right;
$right = $tmp;
}
$a = 1;
$b = 2;
var_dump(swap($a, $b), $a, $b);

[7.1] Symmetric array destructuring

$data = [
[1, 'Tom'],
[2, 'Fred'],
];
// list() style
list($id1, $name1) = $data[0];
// [] style
[$id1, $name1] = $data[0];
// list() style
foreach ($data as list($id, $name)) {
// logic here with $id and $name
}
// [] style
foreach ($data as [$id, $name]) {
// logic here with $id and $name
}
null
int(2)
int(1)

[7.1] Nullable types

function testReturn(): ?string
{
return 'elePHPant';
}
var_dump(testReturn());
function testReturn(): ?string
{
return null;
}
var_dump(testReturn());
function test(?string $name)
{
var_dump($name);
}
test('elePHPant');
test(null);
test();
string(10) "elePHPant"
NULL
string(10) "elePHPant"
NULL
Uncaught Error: Too few arguments to function test(), 0 passed in...

[7.0] Scalar type declarations

declare(strict_type=1);
function test(int $integer, bool $bool, floar $float, string $string)
{
}

[7.0] Return type declarations

function arraysSum(array ...$arrays): array
{
return array_map(function(array $array): int {
return array_sum($array);
}, $arrays);
}

[7.0] Null coalescing operator

$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';

[7.0] Spaceship operator

// Integers
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// Floats
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// Strings
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
?>

[7.0] Constant arrays using define()

define('ANIMALS', [
'dog',
'cat',
'bird'
]);
echo ANIMALS[1]; // outputs "cat"
?>

[7.0] Anonymous classes

$app = new Application;
$app->setLogger(new class implements Logger {
public function log(string $msg) {
echo $msg;
}
});
var_dump($app->getLogger());
?>

[7.0] Unicode codepoint escape syntax

This takes a Unicode codepoint in hexadecimal form, and outputs that codepoint in UTF-8 to a double-quoted string or a heredoc. Any valid codepoint is accepted, with leading 0’s being optional.

echo "\u{aa}";
echo "\u{0000aa}";
echo "\u{9999}";
ª
ª (same as before but with optional leading 0's)

[7.0] Closure::call()

Closure::call() is a more performant, shorthand way of temporarily binding an object scope to a closure and invoking it.

class A {private $x = 1;}
// Pre PHP 7 code
$getXCB = function() {return $this->x;};
$getX = $getXCB->bindTo(new A, 'A'); // intermediate closure
echo $getX();
// PHP 7+ code
$getX = function() {return $this->x;};
echo $getX->call(new A);

[7.0] Filtered unserialize()

This feature seeks to provide better security when unserializing objects on untrusted data. It prevents possible code injections by enabling the developer to whitelist classes that can be unserialized.

// converts all objects into __PHP_Incomplete_Class object
$data = unserialize($foo, ["allowed_classes" => false]);
// converts all objects into __PHP_Incomplete_Class object except those of MyClass and MyClass2
$data = unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]]);
// default behaviour (same as omitting the second argument) that accepts all classes
$data = unserialize($foo, ["allowed_classes" => true]);

[7.0] Group use declarations

use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};

[7.0] list() can always unpack objects implementing ArrayAccess

Previously, list() was not guaranteed to operate correctly with objects implementing ArrayAccess. This has been fixed.

[7.0] preg_replace_callback_array()

The new preg_replace_callback_array() function enables code to be written more cleanly when using the preg_replace_callback() function. Prior to PHP 7, callbacks that needed to be executed per regular expression required the callback function to be polluted with lots of branching.

Now, callbacks can be registered to each regular expression using an associative array, where the key is a regular expression and the value is a callback.

[7.0] Integer division with intdiv()

The new intdiv() function performs an integer division of its operands and returns it.

var_dump(intdiv(3, 2));
var_dump(3/2);
int(1)
float(1.5)

PHP Major migration

Version
7.0 -> 7.1 http://php.net/manual/fr/migration71.php
5.6 -> 7.0 http://php.net/manual/fr/migration70.php
5.5 -> 5.6 http://php.net/manual/fr/migration56.php

Tips (There are micro optimizations)

[7] Packed arrays

Packed arrays is the first great PHP 7 optimization. Packed arrays consume less memory and are a bit faster in many operations than traditional arrays. A packed array must have the following characteristics:

  • The keys are only integers;
  • The keys are inserted into the array in growing only mode.
$a = ['foo', 'bar', 'baz'];
$a = [12 => 'baz', 42 => 'bar', 67 => [] ];

TIPS $pdo->query("SELECT * FROM table LIMIT 10000")->fetchAll(PDO::FETCH_NUM)

[7] ints/floats are free

In PHP 7, the way variables are allocated in memory changed dramatically. They went from being stored on the heap to stack memory pools. As a side effect, you may reuse variable containers for free: no memory allocated. That’s impossible to do in PHP 5, where each variable creation/assignment requires some memory allocation (which is bad for performance).

for ($i=0; $i<10000; $i++) {
$$i = 'foo';
}

VS

for ($i=0; $i<10000; $i++) {
$$i = 42;
}

Alt text

[7] References mismatch

Reference mismatch happens when you pass a non-ref variable to a function argument passed-by-ref, or the opposite. Something like this:

function foo(&$arg) { }
$var = 'str';
foo($var);

Do you know what horrible things happen under the hood in the PHP 5 engine? In PHP 5, whenever there is a reference mismatch, the engine is forced to duplicate the variable before passing it as an argument to a function. As you probably guessed, if the variable contains something big, like a several-thousands-entries array or a big chunk of string; the copy will take a lot of time.

This is because of the way variables and references used to work into PHP 5. When going into the body function, the engine doesn’t know yet if you will change the argument value. If you are, then as the argument is taken by reference, the change must be reflected outside if a reference variable were passed. What if it was not the case (as in our example)? The engine must then create a reference, from the non-reference variable you passed it in the function call. This procedure leads the engine to fully duplicate the variable content in PHP 5 (calling a lot of memcpy() on very sparse pointers, leading to tons of slow memory accesses).

In PHP 7, when the engine wants to create a reference from a non-reference variable, it just wraps the latter into the newly created former, that’s all. There is no memory copy, anywhere. This is because variables work in a very different way internally in PHP 7, and references have been deeply reworked.

Look at this piece of code:

function bar(&$a) { $f = $a; }
$var = range(1,1024);
for ($i=0; $i<1000; $i++) {
bar($var);
}

There is a double mismatch. When you call bar(), you force the engine to create a reference from $var to $a , as the signature says &$a. Then, now that $a is part of a reference set ($var-$a) into the bar() body, you affect it by value to $f: this is another mismatch. $f is not affected by reference, so $a-$f-$var must not be linked together, but $var-$a in one part, and $f alone in another part: you once more force the engine to perform some copies. In PHP 7, creating variables to/from references is pretty light, only copy-on-write may happen after that.

Alt text

[7] Immutable arrays

Immutable arrays are a concept added to PHP 7, and part of the OPCache extension, which I assume you are using. An immutable array is an array full of immutable elements, which are compile-time known and fully resolved values: strings, integers, floats, or arrays containing those. In a word: no dynamic elements, no variables, like in this example:

$ar = [ 'foo', 42, 'bar', [1, 2, 3], 9.87 ];

Such arrays have been optimized in PHP 7. Under PHP 5, those are just plain arrays, there is no difference between an array containing dynamic members (such as $vars), and a static compile-time resolved array. In PHP 7, immutable arrays are not copied nor duplicated as soon as they stay read only.

Here is such an example:

for ($i = 0; $i < 1000; $i++) {
$var[] = [
0 => 'Symfony\\Bundle\\FrameworkBundle\\EventListener\\SessionListener',
1 => 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage',
/* ... go to many immutable items here */
];
}

The above code creates the same big array 1,000 times (truncated, think of it as being a hundred or thousand slots array).

In PHP 5, this array is duplicated in memory 1,000 times. A big array could weight at several hundreds of Kilobytes or even Megabytes, which in this code will be duplicated 1,000 times. Such a waste of memory.

In PHP 7, OPCache flags those arrays as being immutable: the array is created only once, and shares its memory pointer everywhere it is supposed to be used, ending in huge savings of overall memory, especially when dealing with big configuration arrays, like the one shown in the example (which is taken from the Symfony 3 framework).

Let’s see the performance impact:

Alt text

Illustrated example with composer : https://github.com/composer/composer/pull/5174

Alt text

%0A%23%20PHP7%2C%20Stay%20up%20to%20date%20%21%0A%0A@%28Postach.io%29%5Bfeatures%2C%20tips%2C%20performance%2C%20published%2C%20php%5D%0A%0A----------%0A%0A%3E%20TL%3BDR%20Full%20changelog%20http%3A//php.net/ChangeLog-7.php%0A%0A%23%23%20New%20features%0A%0A%23%23%23%20%5B7.1%5D%20HTTP/2%20server%20push%20support%20in%20ext/curl%0A%0A%3ESupport%20for%20server%20push%20has%20been%20added%20to%20the%20CURL%20extension%20%28requires%20version%207.46%20and%20above%29.%20This%20can%20be%20leveraged%20through%20the%20curl_multi_setopt%28%29%20function%20with%20the%20new%20CURLMOPT_PUSHFUNCTION%20constant.%20The%20constants%20CURL_PUSH_OK%20and%20CURL_PUSH_DENY%20have%20also%20been%20added%20so%20that%20the%20execution%20of%20the%20server%20push%20callback%20can%20either%20be%20approved%20or%20denied.%0A%0A%60%60%60php%0A%24mh%20%3D%20curl_multi_init%28%29%3B%0A%0Acurl_multi_setopt%28%24mh%2C%20CURLMOPT_PIPELINING%2C%20CURLPIPE_MULTIPLEX%29%3B%0Acurl_multi_setopt%28%24mh%2C%20CURLMOPT_PUSHFUNCTION%2C%20%24callback%29%3B%0A%0A%24callback%20%3D%20function%28%24parent_ch%2C%20%24pushed_ch%2C%20array%20%24headers%29%20%7B%0A%09return%20CURL_PUSH_OK%3B%0A%7D%3B%0A%60%60%60%0A%0A%3E%20%5BRFC%5D%20https%3A//wiki.php.net/rfc/curl_http2_push%0A%0A%23%23%23%20%5B7.1%5D%20Asynchronous%20signal%20handling%0A%0A%3E%20A%20new%20function%20called%20pcntl_async_signals%28%29%20has%20been%20introduced%20to%20enable%20asynchronous%20signal%20handling%20without%20using%20ticks%20%28which%20introduce%20a%20lot%20of%20overhead%29.%0A%0A%60%60%60php%0Apcntl_async_signals%28true%29%3B%20//%20turn%20on%20async%20signals%0A%0Apcntl_signal%28SIGHUP%2C%20%20function%28%24sig%29%20%7B%0A%20%20%20%20echo%20%22SIGHUP%5Cn%22%3B%0A%7D%29%3B%0A%0Aposix_kill%28posix_getpid%28%29%2C%20SIGHUP%29%3B%0A%60%60%60%0A%0A%3E%20https%3A//github.com/Seldaek/signal-handler%0A%0A%23%23%23%20%5B7.1%5D%20Convert%20callables%20to%20Closures%20with%20Closure%3A%3AfromCallable%28%29%0A%0A%60%60%60php%0Aclass%20Test%0A%7B%0A%20%20%20%20public%20function%20exposeFunction%28%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20return%20Closure%3A%3AfromCallable%28%5B%24this%2C%20%27privateFunction%27%5D%29%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20private%20function%20privateFunction%28%24param%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20var_dump%28%24param%29%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%24privFunc%20%3D%20%28new%20Test%29-%3EexposeFunction%28%29%3B%0A%24privFunc%28%27some%20value%27%29%3B%0A%60%60%60%0A%0A%23%23%23%20%5B7.1%5D%20Support%20for%20negative%20string%20offsets%0A%0A%3E%20Support%20for%20negative%20string%20offsets%20has%20been%20added%20to%20the%20string%20manipulation%20functions%20accepting%20offsets%2C%20as%20well%20as%20to%20string%20indexing%20with%20%5B%5D%20or%20%7B%7D.%20In%20such%20cases%2C%20a%20negative%20offset%20is%20interpreted%20as%20being%20an%20offset%20from%20the%20end%20of%20the%20string.%0A%0A%60%60%60php%0Avar_dump%28%22abcdef%22%5B-2%5D%29%3B%0Avar_dump%28strpos%28%22aabbcc%22%2C%20%22b%22%2C%20-3%29%29%3B%0A%0A%24string%20%3D%20%27bar%27%3B%0Aecho%20%22The%20last%20character%20of%20%27%24string%27%20is%20%27%24string%5B-1%5D%27.%5Cn%22%3B%0A%60%60%60%0A%0A%60%60%60%0Astring%20%281%29%20%22e%22%0Aint%283%29%0AThe%20last%20character%20of%20%27bar%27%20is%20%27r%27.%0A%60%60%60%0A%0A%0A%23%23%23%20%5B7.1%5D%20Support%20for%20keys%20in%20list%28%29%0A%0A%60%60%60php%0A%24data%20%3D%20%5B%0A%20%20%20%20%5B%22id%22%20%3D%3E%201%2C%20%22name%22%20%3D%3E%20%27Tom%27%5D%2C%0A%20%20%20%20%5B%22id%22%20%3D%3E%202%2C%20%22name%22%20%3D%3E%20%27Fred%27%5D%2C%0A%5D%3B%0A%0A//%20list%28%29%20style%0Alist%28%22id%22%20%3D%3E%20%24id1%2C%20%22name%22%20%3D%3E%20%24name1%29%20%3D%20%24data%5B0%5D%3B%0A%0A//%20%5B%5D%20style%0A%5B%22id%22%20%3D%3E%20%24id1%2C%20%22name%22%20%3D%3E%20%24name1%5D%20%3D%20%24data%5B0%5D%3B%0A%0A//%20list%28%29%20style%0Aforeach%20%28%24data%20as%20list%28%22id%22%20%3D%3E%20%24id%2C%20%22name%22%20%3D%3E%20%24name%29%29%20%7B%0A%20%20%20%20//%20logic%20here%20with%20%24id%20and%20%24name%0A%7D%0A%0A//%20%5B%5D%20style%0Aforeach%20%28%24data%20as%20%5B%22id%22%20%3D%3E%20%24id%2C%20%22name%22%20%3D%3E%20%24name%5D%29%20%7B%0A%20%20%20%20//%20logic%20here%20with%20%24id%20and%20%24name%0A%7D%0A%60%60%60%0A%0A%23%23%23%20%5B7.1%5D%20Multi%20catch%20exception%20handling%0A%0A%60%60%60php%0Atry%20%7B%0A%20%20%20%20//%20some%20code%0A%7D%20catch%20%28FirstException%20%7C%20SecondException%20%24e%29%20%7B%0A%20%20%20%20//%20handle%20first%20and%20second%20exceptions%0A%7D%0A%60%60%60%0A%0A%23%23%23%20%5B7.1%5D%20Iterable%20pseudo-type%0A%0A%60%60%60php%0Afunction%20iterator%28iterable%20%24iter%29%0A%7B%0A%20%20%20%20foreach%20%28%24iter%20as%20%24val%29%20%7B%0A%20%20%20%20%20%20%20%20//%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%0A%23%23%23%20%5B7.1%5D%20Class%20constant%20visibility%20%0A%0A%60%60%60php%0Aclass%20ConstDemo%0A%7B%0A%20%20%20%20const%20PUBLIC_CONST_A%20%3D%201%3B%0A%20%20%20%20public%20const%20PUBLIC_CONST_B%20%3D%202%3B%0A%20%20%20%20protected%20const%20PROTECTED_CONST%20%3D%203%3B%0A%20%20%20%20private%20const%20PRIVATE_CONST%20%3D%204%3B%0A%7D%0A%60%60%60%0A%0A%23%23%23%20%5B7.1%5D%20Void%20functions%0A%0A%60%60%60php%0Afunction%20swap%28%26%24left%2C%20%26%24right%29%20%3A%20void%0A%7B%0A%20%20%20%20if%20%28%24left%20%3D%3D%3D%20%24right%29%20%7B%0A%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%24tmp%20%3D%20%24left%3B%0A%20%20%20%20%24left%20%3D%20%24right%3B%0A%20%20%20%20%24right%20%3D%20%24tmp%3B%0A%7D%0A%0A%24a%20%3D%201%3B%0A%24b%20%3D%202%3B%0Avar_dump%28swap%28%24a%2C%20%24b%29%2C%20%24a%2C%20%24b%29%3B%0A%60%60%60%0A%0A%23%23%23%20%5B7.1%5D%20Symmetric%20array%20destructuring%0A%0A%60%60%60php%0A%24data%20%3D%20%5B%0A%20%20%20%20%5B1%2C%20%27Tom%27%5D%2C%0A%20%20%20%20%5B2%2C%20%27Fred%27%5D%2C%0A%5D%3B%0A%0A//%20list%28%29%20style%0Alist%28%24id1%2C%20%24name1%29%20%3D%20%24data%5B0%5D%3B%0A%0A//%20%5B%5D%20style%0A%5B%24id1%2C%20%24name1%5D%20%3D%20%24data%5B0%5D%3B%0A%0A//%20list%28%29%20style%0Aforeach%20%28%24data%20as%20list%28%24id%2C%20%24name%29%29%20%7B%0A%20%20%20%20//%20logic%20here%20with%20%24id%20and%20%24name%0A%7D%0A%0A//%20%5B%5D%20style%0Aforeach%20%28%24data%20as%20%5B%24id%2C%20%24name%5D%29%20%7B%0A%20%20%20%20//%20logic%20here%20with%20%24id%20and%20%24name%0A%7D%0A%60%60%60%0A%0A%60%60%60%0Anull%0Aint%282%29%0Aint%281%29%0A%60%60%60%0A%0A%23%23%23%20%5B7.1%5D%20Nullable%20types%0A%0A%60%60%60php%0A%0Afunction%20testReturn%28%29%3A%20%3Fstring%0A%7B%0A%20%20%20%20return%20%27elePHPant%27%3B%0A%7D%0A%0Avar_dump%28testReturn%28%29%29%3B%0A%0Afunction%20testReturn%28%29%3A%20%3Fstring%0A%7B%0A%20%20%20%20return%20null%3B%0A%7D%0A%0Avar_dump%28testReturn%28%29%29%3B%0A%0Afunction%20test%28%3Fstring%20%24name%29%0A%7B%0A%20%20%20%20var_dump%28%24name%29%3B%0A%7D%0A%0Atest%28%27elePHPant%27%29%3B%0Atest%28null%29%3B%0Atest%28%29%3B%0A%60%60%60%0A%0A%60%60%60%0Astring%2810%29%20%22elePHPant%22%0ANULL%0Astring%2810%29%20%22elePHPant%22%0ANULL%0AUncaught%20Error%3A%20Too%20few%20arguments%20to%20function%20test%28%29%2C%200%20passed%20in...%0A%60%60%60%0A%0A%23%23%23%20%5B7.0%5D%20Scalar%20type%20declarations%20%0A%0A%60%60%60%20php%0A%3C%3Fphp%0Adeclare%28strict_type%3D1%29%3B%0A%0Afunction%20test%28int%20%24integer%2C%20bool%20%24bool%2C%20floar%20%24float%2C%20string%20%24string%29%0A%7B%0A%0A%7D%0A%60%60%60%0A%0A%23%23%23%20%5B7.0%5D%20Return%20type%20declarations%0A%0A%60%60%60php%0A%3C%3Fphp%0A%0Afunction%20arraysSum%28array%20...%24arrays%29%3A%20array%0A%7B%0A%20%20%20%20return%20array_map%28function%28array%20%24array%29%3A%20int%20%7B%0A%20%20%20%20%20%20%20%20return%20array_sum%28%24array%29%3B%0A%20%20%20%20%7D%2C%20%24arrays%29%3B%0A%7D%0A%0A%60%60%60%0A%0A%23%23%23%20%5B7.0%5D%20Null%20coalescing%20operator%0A%0A%60%60%60php%0A%24username%20%3D%20%24_GET%5B%27user%27%5D%20%3F%3F%20%24_POST%5B%27user%27%5D%20%3F%3F%20%27nobody%27%3B%0A%60%60%60%0A%0A%23%23%23%20%5B7.0%5D%20Spaceship%20operator%0A%0A%60%60%60php%0A%3C%3Fphp%0A//%20Integers%0Aecho%201%20%3C%3D%3E%201%3B%20//%200%0Aecho%201%20%3C%3D%3E%202%3B%20//%20-1%0Aecho%202%20%3C%3D%3E%201%3B%20//%201%0A%0A//%20Floats%0Aecho%201.5%20%3C%3D%3E%201.5%3B%20//%200%0Aecho%201.5%20%3C%3D%3E%202.5%3B%20//%20-1%0Aecho%202.5%20%3C%3D%3E%201.5%3B%20//%201%0A%20%0A//%20Strings%0Aecho%20%22a%22%20%3C%3D%3E%20%22a%22%3B%20//%200%0Aecho%20%22a%22%20%3C%3D%3E%20%22b%22%3B%20//%20-1%0Aecho%20%22b%22%20%3C%3D%3E%20%22a%22%3B%20//%201%0A%3F%3E%0A%60%60%60%0A%0A%23%23%23%20%5B7.0%5D%20Constant%20arrays%20using%20define%28%29%0A%0A%60%60%60php%0A%3C%3Fphp%0Adefine%28%27ANIMALS%27%2C%20%5B%0A%20%20%20%20%27dog%27%2C%0A%20%20%20%20%27cat%27%2C%0A%20%20%20%20%27bird%27%0A%5D%29%3B%0A%0Aecho%20ANIMALS%5B1%5D%3B%20//%20outputs%20%22cat%22%0A%3F%3E%0A%60%60%60%0A%0A%23%23%23%20%5B7.0%5D%20Anonymous%20classes%0A%0A%60%60%60php%0A%3C%3Fphp%0A%0A%24app%20%3D%20new%20Application%3B%0A%24app-%3EsetLogger%28new%20class%20implements%20Logger%20%7B%0A%20%20%20%20public%20function%20log%28string%20%24msg%29%20%7B%0A%20%20%20%20%20%20%20%20echo%20%24msg%3B%0A%20%20%20%20%7D%0A%7D%29%3B%0A%0Avar_dump%28%24app-%3EgetLogger%28%29%29%3B%0A%3F%3E%0A%60%60%60%0A%0A%23%23%23%20%5B7.0%5D%20Unicode%20codepoint%20escape%20syntax%0A%0A%3E%20This%20takes%20a%20Unicode%20codepoint%20in%20hexadecimal%20form%2C%20and%20outputs%20that%20codepoint%20in%20UTF-8%20to%20a%20double-quoted%20string%20or%20a%20heredoc.%20Any%20valid%20codepoint%20is%20accepted%2C%20with%20leading%200%27s%20being%20optional.%0A%0A%60%60%60php%0Aecho%20%22%5Cu%7Baa%7D%22%3B%0Aecho%20%22%5Cu%7B0000aa%7D%22%3B%0Aecho%20%22%5Cu%7B9999%7D%22%3B%0A%60%60%60%0A%0A%60%60%60%0A%AA%0A%AA%20%28same%20as%20before%20but%20with%20optional%20leading%200%27s%29%0A%u9999%0A%60%60%60%0A%0A%23%23%23%20%5B7.0%5D%20Closure%3A%3Acall%28%29%0A%0A%5BClosure%3A%3Acall%28%29%5D%28http%3A//php.net/manual/fr/closure.call.php%29%20is%20a%20more%20performant%2C%20shorthand%20way%20of%20temporarily%20binding%20an%20object%20scope%20to%20a%20closure%20and%20invoking%20it.%0A%0A%60%60%60php%0A%3C%3Fphp%0Aclass%20A%20%7Bprivate%20%24x%20%3D%201%3B%7D%0A%0A//%20Pre%20PHP%207%20code%0A%24getXCB%20%3D%20function%28%29%20%7Breturn%20%24this-%3Ex%3B%7D%3B%0A%24getX%20%3D%20%24getXCB-%3EbindTo%28new%20A%2C%20%27A%27%29%3B%20//%20intermediate%20closure%0Aecho%20%24getX%28%29%3B%0A%0A//%20PHP%207+%20code%0A%24getX%20%3D%20function%28%29%20%7Breturn%20%24this-%3Ex%3B%7D%3B%0Aecho%20%24getX-%3Ecall%28new%20A%29%3B%0A%60%60%60%0A%0A%23%23%23%20%5B7.0%5D%20Filtered%20unserialize%28%29%0A%0A%3E%20This%20feature%20seeks%20to%20provide%20better%20security%20when%20unserializing%20objects%20on%20untrusted%20data.%20It%20prevents%20possible%20code%20injections%20by%20enabling%20the%20developer%20to%20whitelist%20classes%20that%20can%20be%20unserialized.%20%0A%0A%60%60%60php%0A//%20converts%20all%20objects%20into%20__PHP_Incomplete_Class%20object%0A%24data%20%3D%20unserialize%28%24foo%2C%20%5B%22allowed_classes%22%20%3D%3E%20false%5D%29%3B%0A%0A//%20converts%20all%20objects%20into%20__PHP_Incomplete_Class%20object%20except%20those%20of%20MyClass%20and%20MyClass2%0A%24data%20%3D%20unserialize%28%24foo%2C%20%5B%22allowed_classes%22%20%3D%3E%20%5B%22MyClass%22%2C%20%22MyClass2%22%5D%5D%29%3B%0A%0A//%20default%20behaviour%20%28same%20as%20omitting%20the%20second%20argument%29%20that%20accepts%20all%20classes%0A%24data%20%3D%20unserialize%28%24foo%2C%20%5B%22allowed_classes%22%20%3D%3E%20true%5D%29%3B%0A%60%60%60%0A%0A%23%23%23%20%5B7.0%5D%20Group%20use%20declarations%0A%0A%60%60%60php%0Ause%20some%5Cnamespace%5C%7BClassA%2C%20ClassB%2C%20ClassC%20as%20C%7D%3B%0Ause%20function%20some%5Cnamespace%5C%7Bfn_a%2C%20fn_b%2C%20fn_c%7D%3B%0Ause%20const%20some%5Cnamespace%5C%7BConstA%2C%20ConstB%2C%20ConstC%7D%3B%0A%60%60%60%0A%0A%23%23%23%20%5B7.0%5D%20list%28%29%20can%20always%20unpack%20objects%20implementing%20ArrayAccess%0A%0A%3E%20Previously%2C%20list%28%29%20was%20not%20guaranteed%20to%20operate%20correctly%20with%20objects%20implementing%20ArrayAccess.%20This%20has%20been%20fixed.%0A%0A%23%23%23%20%5B7.0%5D%20preg_replace_callback_array%28%29%0A%0A%3E%20The%20new%20%5Bpreg_replace_callback_array%28%29%5D%28http%3A//php.net/manual/fr/function.preg-replace-callback-array.php%29%20function%20enables%20code%20to%20be%20written%20more%20cleanly%20when%20using%20the%20preg_replace_callback%28%29%20function.%20Prior%20to%20PHP%207%2C%20callbacks%20that%20needed%20to%20be%20executed%20per%20regular%20expression%20required%20the%20callback%20function%20to%20be%20polluted%20with%20lots%20of%20branching.%0A%0ANow%2C%20callbacks%20can%20be%20registered%20to%20each%20regular%20expression%20using%20an%20associative%20array%2C%20where%20the%20key%20is%20a%20regular%20expression%20and%20the%20value%20is%20a%20callback.%0A%0A%23%23%23%20%5B7.0%5D%20Integer%20division%20with%20intdiv%28%29%0A%0A%3E%20The%20new%20%5Bintdiv%28%29%5D%28http%3A//php.net/manual/fr/function.intdiv.php%29%20function%20performs%20an%20integer%20division%20of%20its%20operands%20and%20returns%20it.%0A%0A%60%60%60php%0Avar_dump%28intdiv%283%2C%202%29%29%3B%0Avar_dump%283/2%29%3B%0A%60%60%60%0A%0A%60%60%60%0Aint%281%29%0Afloat%281.5%29%0A%60%60%60%0A%09%0A%0A%23%23%20%20PHP%20Major%20migration%0A%0A%7C%20Version%20%20%20%20%20%20%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7C%0A%7C%20%3A----------%20%7C%20----------------------------------------------------------------------------------%3A%7C%0A%7C%207.0%20-%3E%207.1%20%20%7C%5Bhttp%3A//php.net/manual/fr/migration71.php%5D%28http%3A//php.net/manual/fr/migration71.php%29%7C%0A%7C%205.6%20-%3E%207.0%20%20%7C%5Bhttp%3A//php.net/manual/fr/migration70.php%5D%28http%3A//php.net/manual/fr/migration70.php%29%7C%20%0A%7C%205.5%20-%3E%205.6%20%20%7C%5Bhttp%3A//php.net/manual/fr/migration56.php%5D%28http%3A//php.net/manual/fr/migration56.php%29%7C%20%0A%0A%0A%23%23%20Tips%20%28There%20are%20micro%20optimizations%29%0A%0A%23%23%23%20%20%5B7%5D%20Packed%20arrays%0A%0A%3EPacked%20arrays%20is%20the%20first%20great%20PHP%207%20optimization.%20Packed%20arrays%20consume%20less%20memory%20and%20are%20a%20bit%20faster%20in%20many%20operations%20than%20traditional%20arrays.%20A%20packed%20array%20must%20have%20the%20following%20characteristics%3A%0A*%20The%20keys%20are%20only%20integers%3B%0A*%20The%20keys%20are%20inserted%20into%20the%20array%20in%20growing%20only%20mode.%0A%60%60%60php%0A%24a%20%3D%20%5B%27foo%27%2C%20%27bar%27%2C%20%27baz%27%5D%3B%0A%24a%20%3D%20%5B12%20%3D%3E%20%27baz%27%2C%2042%20%3D%3E%20%27bar%27%2C%2067%20%3D%3E%20%5B%5D%20%5D%3B%0A%60%60%60%0A%0A%3E%20**TIPS**%20%20%60%24pdo-%3Equery%28%22SELECT%20*%20FROM%20table%20LIMIT%2010000%22%29-%3EfetchAll%28PDO%3A%3AFETCH_NUM%29%60%20%0A%0A%23%23%23%20%5B7%5D%20ints/floats%20are%20free%0A%0A%3E%20In%20PHP%207%2C%20the%20way%20variables%20are%20allocated%20in%20memory%20changed%20dramatically.%20They%20went%20from%20being%20stored%20on%20the%20heap%20to%20stack%20memory%20pools.%20As%20a%20side%20effect%2C%20you%20may%20reuse%20variable%20containers%20for%20free%3A%20no%20memory%20allocated.%20That%u2019s%20impossible%20to%20do%20in%20PHP%205%2C%20where%20each%20variable%20creation/assignment%20requires%20some%20memory%20allocation%20%28which%20is%20bad%20for%20performance%29.%0A%0A%0A%60%60%60php%0Afor%20%28%24i%3D0%3B%20%24i%3C10000%3B%20%24i++%29%20%7B%0A%09%24%24i%20%3D%20%27foo%27%3B%0A%7D%0A%60%60%60%0A**VS**%0A%60%60%60php%0Afor%20%28%24i%3D0%3B%20%24i%3C10000%3B%20%24i++%29%20%7B%0A%09%24%24i%20%3D%2042%3B%0A%7D%0A%60%60%60%0A%0A%21%5BAlt%20text%5D%28./variable-integer.png%29%0A%0A%0A%23%23%23%20%5B7%5D%20References%20mismatch%0A%0AReference%20mismatch%20happens%20when%20you%20pass%20a%20non-ref%20variable%20to%20a%20function%20argument%20passed-by-ref%2C%20or%20the%20opposite.%20Something%20like%20this%3A%0A%0A%60%60%60php%0Afunction%20foo%28%26%24arg%29%20%7B%20%7D%0A%24var%20%3D%20%27str%27%3B%0Afoo%28%24var%29%3B%0A%60%60%60%0A%0ADo%20you%20know%20what%20horrible%20things%20happen%20under%20the%20hood%20in%20the%20PHP%205%20engine%3F%20In%20PHP%205%2C%20whenever%20there%20is%20a%20reference%20mismatch%2C%20the%20engine%20is%20forced%20to%20duplicate%20the%20variable%20before%20passing%20it%20as%20an%20argument%20to%20a%20function.%20As%20you%20probably%20guessed%2C%20if%20the%20variable%20contains%20something%20big%2C%20like%20a%20several-thousands-entries%20array%20or%20a%20big%20chunk%20of%20string%3B%20the%20copy%20will%20take%20a%20lot%20of%20time.%0A%0AThis%20is%20because%20of%20the%20way%20variables%20and%20references%20used%20to%20work%20into%20PHP%205.%20When%20going%20into%20the%20body%20function%2C%20the%20engine%20doesn%u2019t%20know%20yet%20if%20you%20will%20change%20the%20argument%20value.%20If%20you%20are%2C%20then%20as%20the%20argument%20is%20taken%20by%20reference%2C%20the%20change%20must%20be%20reflected%20outside%20if%20a%20reference%20variable%20were%20passed.%20What%20if%20it%20was%20not%20the%20case%20%28as%20in%20our%20example%29%3F%20The%20engine%20must%20then%20create%20a%20reference%2C%20from%20the%20non-reference%20variable%20you%20passed%20it%20in%20the%20function%20call.%20This%20procedure%20leads%20the%20engine%20to%20fully%20duplicate%20the%20variable%20content%20in%20PHP%205%20%28calling%20a%20lot%20of%20memcpy%28%29%20on%20very%20sparse%20pointers%2C%20leading%20to%20tons%20of%20slow%20memory%20accesses%29.%0A%0AIn%20PHP%207%2C%20when%20the%20engine%20wants%20to%20create%20a%20reference%20from%20a%20non-reference%20variable%2C%20it%20just%20wraps%20the%20latter%20into%20the%20newly%20created%20former%2C%20that%u2019s%20all.%20There%20is%20no%20memory%20copy%2C%20anywhere.%20This%20is%20because%20variables%20work%20in%20a%20very%20different%20way%20internally%20in%20PHP%207%2C%20and%20references%20have%20been%20deeply%20reworked.%0A%0ALook%20at%20this%20piece%20of%20code%3A%0A%0A%60%60%60php%0Afunction%20bar%28%26%24a%29%20%7B%20%24f%20%3D%20%24a%3B%20%7D%0A%20%0A%24var%20%3D%20range%281%2C1024%29%3B%0A%20%0Afor%20%28%24i%3D0%3B%20%24i%3C1000%3B%20%24i++%29%20%7B%0Abar%28%24var%29%3B%0A%7D%0A%60%60%60%0A%0AThere%20is%20a%20double%20mismatch.%20When%20you%20call%20bar%28%29%2C%20you%20force%20the%20engine%20to%20create%20a%20reference%20from%20%60%24var%60%20%20to%20%60%24a%60%20%2C%20as%20the%20signature%20says%20%60%26%24a%60.%20Then%2C%20now%20that%20%60%24a%60%20is%20part%20of%20a%20reference%20set%20%28%60%24var-%24a%60%29%20into%20the%20bar%28%29%20body%2C%20you%20affect%20it%20by%20value%20to%20%60%24f%60%3A%20this%20is%20another%20mismatch.%20%60%24f%60%20is%20not%20affected%20by%20reference%2C%20so%20%60%24a-%24f-%24var%60%20must%20not%20be%20linked%20together%2C%20but%20%60%24var-%24a%60%20in%20one%20part%2C%20and%20%60%24f%60%20alone%20in%20another%20part%3A%20you%20once%20more%20force%20the%20engine%20to%20perform%20some%20copies.%20In%20PHP%207%2C%20creating%20variables%20to/from%20references%20is%20pretty%20light%2C%20only%20copy-on-write%20may%20happen%20after%20that.%0A%0A%21%5BAlt%20text%5D%28./ref-mis.png%29%0A%0A%0A%23%23%23%20%5B7%5D%20Immutable%20arrays%0A%0AImmutable%20arrays%20are%20a%20concept%20added%20to%20PHP%207%2C%20and%20part%20of%20the%20OPCache%20extension%2C%20which%20I%20assume%20you%20are%20using.%20An%20immutable%20array%20is%20an%20array%20full%20of%20immutable%20elements%2C%20which%20are%20compile-time%20known%20and%20fully%20resolved%20values%3A%20strings%2C%20integers%2C%20floats%2C%20or%20arrays%20containing%20those.%20In%20a%20word%3A%20no%20dynamic%20elements%2C%20no%20variables%2C%20like%20in%20this%20example%3A%0A%0A%60%60%60php%0A%24ar%20%3D%20%5B%20%27foo%27%2C%2042%2C%20%27bar%27%2C%20%5B1%2C%202%2C%203%5D%2C%209.87%20%5D%3B%0A%60%60%60%0A%0ASuch%20arrays%20have%20been%20optimized%20in%20PHP%207.%20Under%20PHP%205%2C%20those%20are%20just%20plain%20arrays%2C%20there%20is%20no%20difference%20between%20an%20array%20containing%20dynamic%20members%20%28such%20as%20%60%24vars%60%29%2C%20and%20a%20static%20compile-time%20resolved%20array.%20In%20PHP%207%2C%20immutable%20arrays%20are%20not%20copied%20nor%20duplicated%20as%20soon%20as%20they%20stay%20read%20only.%0A%0AHere%20is%20such%20an%20example%3A%0A%0A%60%60%60php%0Afor%20%28%24i%20%3D%200%3B%20%24i%20%3C%201000%3B%20%24i++%29%20%7B%0A%24var%5B%5D%20%3D%20%5B%0A%20%200%20%3D%3E%20%27Symfony%5C%5CBundle%5C%5CFrameworkBundle%5C%5CEventListener%5C%5CSessionListener%27%2C%0A%20%201%20%3D%3E%20%27Symfony%5C%5CComponent%5C%5CHttpFoundation%5C%5CSession%5C%5CStorage%5C%5CNativeSessionStorage%27%2C%0A%20%20/*%20...%20go%20to%20many%20immutable%20items%20here%20*/%0A%20%20%5D%3B%0A%7D%0A%60%60%60%0A%0AThe%20above%20code%20creates%20the%20same%20big%20array%201%2C000%20times%20%28truncated%2C%20think%20of%20it%20as%20being%20a%20hundred%20or%20thousand%20slots%20array%29.%0A%0AIn%20PHP%205%2C%20this%20array%20is%20duplicated%20in%20memory%201%2C000%20times.%20A%20big%20array%20could%20weight%20at%20several%20hundreds%20of%20Kilobytes%20or%20even%20Megabytes%2C%20which%20in%20this%20code%20will%20be%20duplicated%201%2C000%20times.%20Such%20a%20waste%20of%20memory.%0A%0AIn%20PHP%207%2C%20OPCache%20flags%20those%20arrays%20as%20being%20immutable%3A%20the%20array%20is%20created%20only%20once%2C%20and%20shares%20its%20memory%20pointer%20everywhere%20it%20is%20supposed%20to%20be%20used%2C%20ending%20in%20huge%20savings%20of%20overall%20memory%2C%20especially%20when%20dealing%20with%20big%20configuration%20arrays%2C%20like%20the%20one%20shown%20in%20the%20example%20%28which%20is%20taken%20from%20the%20Symfony%203%20framework%29.%0A%0ALet%u2019s%20see%20the%20performance%20impact%3A%0A%0A%21%5BAlt%20text%5D%28./immutable-arrays.png%29%0A%0A%3E%20Illustrated%20example%20with%20composer%20%3A%20https%3A//github.com/composer/composer/pull/5174%0A%0A%21%5BAlt%20text%5D%28./Screenshot%20Thu%20Dec%2022%202016%2011%3A34%3A35%20GMT+0100%20CET%201517x1036.png%29%0A%0A%0A%0A