The most exciting
features of PHP 7.1

by Enrico Zimuel
Senior Software Engineer
Zend, a Rogue Wave Company (USA)


PHPDay 2017, Verona, 12th May

About me

PHP 7.1

  • 7.1.0 released (01 Dec 2016)
  • Latest is 7.1.5 (11 May 2017)

7.1 by numbers

  • 376 bug fixes
  • 12 new features
  • 13 new functions
  • 36 new global constants
  • 20 backward incompatible changes
  • 2 deprecated features
  • 16 changed functions
  • 7 other changes

New features

Nullable types

  • For parameters and return values
  • Prefixing the type name with a ?
  • NULL can be passed as an argument,
    or returned as a value

Example


function hi(?string $name): ?string
{
    if (null === $name) {
        return null;
    }
    return 'Hello ' . $name;
}

echo hi(null); // returns null
echo hi('Enrico'); // returns 'Hello Enrico'
echo hi(); // Fatal error: Too few arguments to function hi(), 0 passed

OOP Example


interface Fooable {
    function foo(): ?Fooable;
}
interface StrictFooable extends Fooable {
    function foo(): Fooable; // valid
}

interface Fooable {
    function foo(): Fooable;
}
interface LooseFooable extends Fooable {
    function foo(): ?Fooable; // invalid
}

OOP Example (2)


interface Fooable {
    function foo(Fooable $f);
}
interface LooseFoo extends Fooable {
    function foo(?Fooable $f); // valid
}

interface Fooable {
    function foo(?Fooable $f);
}
interface StrictFoo extends Fooable {
    function foo(Fooable $f); // invalid
}

Void Return Type


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); // null, int(2), int(1)

Array destructuring


$data = [
    ['foo', 'bar', 'baz']
];
[$a, $b] = $data[0];
var_dump($a, $b); // string(3) "foo", string(3) "bar"
[$a, , $c] = $data[0];
var_dump($a, $c); // string(3) "foo", string(3) "baz"
foreach ($data as [$a, $b, $c]) {
    var_dump($a, $b, $c);
    // string(3) "foo"
    // string(3) "bar"
    // string(3) "baz"
}

Support for keys

Specify keys in list(), or its new shorthand [] syntax


$data = [
    'a' => 'foo',
    'b' => 'bar',
    'c' => 'baz'
];
list('a' => $a, 'b' => $b, 'c' => $c) = $data;
var_dump($a, $b, $c);
// string(3) "foo"
// string(3) "bar"
// string(3) "baz"
['a' => $a, 'b' => $b, 'c' => $c] = $data;
var_dump($a, $b, $c);
// string(3) "foo"
// string(3) "bar"
// string(3) "baz"

No mix list() and [ ]


// Not allowed
list([$a, $b], [$c, $d]) = [[1, 2], [3, 4]];
[list($a, $b), list($c, $d)] = [[1, 2], [3, 4]];

// Allowed
list(list($a, $b), list($c, $d)) = [[1, 2], [3, 4]];
[[$a, $b], [$c, $d]] = [[1, 2], [3, 4]];

Iterable

  • Added the iterable pseudo-type
  • It accepts array or Traversable
  • Can be used in parameter and return types

Example


function foo(iterable $iterable): void
{
    foreach ($iterable as $value) {
        var_dump($value);
    }
}

foo([1,2,3]);
foo(new ArrayIterator([1,2,3]));

Class CONST visibility


class ConstDemo
{
    const PUBLIC_CONST_A = 1; // default to public

    public const PUBLIC_CONST_B = 2;
    protected const PROTECTED_CONST = 3;
    private const PRIVATE_CONST = 4;
}

Using Reflection


$obj = new ReflectionClass("ConstDemo");
foreach ($obj->getReflectionConstants() as $const) {
    var_dump($const); // object(ReflectionClassConstant)
    var_dump($const->getName());
    var_dump($const->getValue());
    var_dump($const->isPublic());
    var_dump($const->isPrivate());
    var_dump($const->isProtected());
}

ReflectionClassConstant is not documented (BUG #74261)

Multiple catch {}


try {
   // Some code...
} catch (ExceptionType1 $e) {
   // Code to handle the exception
} catch (ExceptionType2 $e) {
   // Same code to handle the exception
} catch (Exception $e) {
   // ...
}

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

Negative string offsets


var_dump("abcdef"[-2]); // string(1) "e"
var_dump("abcdef"[-7]); // string(0) "", PHP Notice offset
// strpos
var_dump(strpos("aabbcc", "b", -3)); // int(3)

// get the last character of a string
$last = substr($foo, -1); // before PHP 7.1
$last = $foo[-1];

Async signal handling

pcntl_async_signals() has been introduced to enable asynchronous signal handling without using ticks


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

Closure from callable


class Test
{
    public function exposeFunction()
    {
        return Closure::fromCallable([$this, 'privateFunction']);
    }

    private function privateFunction($param)
    {
        var_dump($param);
    }
}

$privFunc = (new Test)->exposeFunction();
var_dump($privFunc); // object(Closure)
$privFunc('some value'); // string(10) "some value"

OpenSSL AEAD

Authenticated Encrypt with Associated Data (AEAD)

Support GCM and CCM encryption modes

GCM is 3x faster than CCM. See this benchmark

More info on Authenticated Encryption in PHP 7.1

openssl_encrypt()


string openssl_encrypt(
    string $data,
    string $method,
    string $password,
    [ int $options = 0 ],
    [ string $iv = "" ],
    [ string &$tag = NULL ],
    [ string $aad = "" ],
    [ int $tag_length = 16 ]
)

$tag contains the authentication hash

openssl_decrypt()


string openssl_decrypt(
    string $data,
    string $method,
    string $password,
    [ int $options = 0 ],
    [ string $iv = "" ],
    [ string $tag = "" ],
    [ string $aad = "" ]
)

$tag is the authentication hash

Encrypt example


$algo = 'aes-256-gcm';
$iv   = random_bytes(openssl_cipher_iv_length($algo));
$key  = random_bytes(32); // 256 bit
$data = random_bytes(1024); // 1 Kb of random data
$ciphertext = openssl_encrypt(
    $data,
    $algo,
    $key,
    OPENSSL_RAW_DATA,
    $iv,
    $tag
);
// output is $ciphertext and $tag

$tag is the authentication hash

Decrypt example


$decrypt = openssl_decrypt(
    $ciphertext,
    $algo,
    $key,
    OPENSSL_RAW_DATA,
    $iv,
    $tag
);
if (false === $decrypt) {
    throw new Exception(sprintf(
        "OpenSSL error: %s", openssl_error_string()
    ));
}
printf ("Decryption %s\n", $data === $decrypt ? 'Ok' : 'Failed');

$tag is the authentication hash

HTTP/2 Server Push

  • Server push has been added to CURL 7.46+
  • Use curl_multi_setopt() function with the new CURLMOPT_PUSHFUNCTION constant
  • Added CURL_PUSH_OK and CURL_PUSH_DENY to approve or deny the callback execution

Example


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

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://localhost:8080/index.html");
curl_setopt($ch, CURLOPT_HTTP_VERSION, 3);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // self-signed cert
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // self-signed cert
curl_multi_add_handle($mh, $ch);

Example (2)


$active = null;
do {
    $status = curl_multi_exec($mh, $active);
    do {
        $info = curl_multi_info_read($mh);
        if (false !== $info && $info['msg'] == CURLMSG_DONE) {
            $handle = $info['handle'];
            if ($handle !== null) {
                $transfers--; // decrement remaining requests
                $body = curl_multi_getcontent($info['handle']);
                curl_multi_remove_handle($mh, $handle);
                curl_close($handle);
            }
        }
    } while ($info);
} while ($transfers);
curl_multi_close($mh);

New hash functions

Added hash_hkdf() function to support HKDF (RFC 5869)


$key = random_bytes(32);
$salt = random_bytes(16);

$encryptKey = hash_hkdf('sha256', $key, 32, 'encrypt', $salt);
$authKey = hash_hkdf('sha256', $key, 32, 'auth', $salt);

var_dump($encryptKey !== $authKey); // bool(true)

Added SHA3 support (224, 256, 384, and 512)


$hash = hash('sha3-224', 'This is a text');
var_dump($hash);
// string(56)"9209f5869ad03ac11549902b3c83fe8e6b7e1cd1614ab4291587db43"

To summarize

  • Nullable and void return types
  • Array destructuring
  • Iterable
  • Class CONST visibility
  • Multiple catch {}
  • Async signal handling
  • Closure from callable
  • OpenSSL AEAD
  • HTTP/2 Server Push
  • New hash functions

Thanks!

Rate this talk at https://joind.in/talk/935fc

Contact me: enrico.zimuel [at] roguewave.com

Follow me: @ezimuel



Creative Commons License
This work is licensed under a
Creative Commons Attribution-ShareAlike 3.0 Unported License.
I used reveal.js to make this presentation.