PHP 7 features at a glance

We may know PHP made revolutionary changes in version 7. One of the major changes is its performance are double than the previous versions.
In this article, I’ll try to discuss some features from PHP7.0 & PHP7.1 in shortly.

Scalar type declarations

The scalar type declaration is similar to type hints. In PHP 7, it is extended for the supports to string, int, boolean, float

It has two modes coercive (default) & strict.

In coercive mode, the arguments are automatically cast as you’ve defined. Eg. string, int, boolean, float, array, callable but when you use declare(strict_types=1); at the top of the file, then it will throw a type error.

// Coercive mode
function sumOfInts(int ...$ints)
{
    return array_sum($ints);
}

var_dump(sumOfInts(2, '3', 4.1));

Return type declarations

Same as argument type declarations, PHP 7 also introduced return type declarations with same types.

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

print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));

Null coalescing operator

The null coalescing operator is shorthand operator to check value with isset() in the ternary operator.

// Pre PHP 7 code
$route = isset($_GET['route']) ? $_GET['route'] : 'index';

// PHP 7+ code
$route = $_GET['route'] ?? 'index';

Spaceship operator

The spaceship operator is used to compare two operands in three ways.

If the return is 0, then both operands are equal.
If the return is -1, then the right operand is greater than left operand.
If the return is 1, then the left operand is greater than right operand.

echo 1 <=> 1; // 0
echo 1.5 <=> 2.5; // -1
echo "b" <=> "a"; // 1

Constant arrays

PHP 7 allows user to define arrays as constant.

define('ANIMALS', [
    'dog',
    'cat',
    'bird'
]);

echo ANIMALS[1]; // outputs "cat"

Anonymous classes

The anonymous classes feature makes life easier, class can be instantiated and defined at the same time.

class Application {
    private $logger;

    public function getLogger() {
         return $this->logger;
    }

    public function setLogger($logger) {
         $this->logger = $logger;
    }
}

$app = new Application;
$app->setLogger(new class {
    public function log($msg) {
        echo $msg;
    }
});

var_dump($app->getLogger());

Closure::call()

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

class A {private $x = 1;}

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

// PHP 7+ code
$getX = function() {return $this->x;};
echo $getX->call(new A);

Group use declarations

The use keyword has the ability to import a group of classes, functions and constants from same namespace.

// Pre PHP 7 code
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;

use function some\namespace\fn_a;
use function some\namespace\fn_b;
use function some\namespace\fn_c;

use const some\namespace\ConstA;
use const some\namespace\ConstB;
use const some\namespace\ConstC;

// PHP 7+ code
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};

Generator Return Expressions

The generator can now use return expression to return any value, and the value can be fetched by Generator::getReturn()

// IIFE syntax now possible - see the Uniform Variable Syntax subsection in the Changes section
$gen = (function() {
    yield 1;
    yield 2;

    return 10;
})();

foreach ($gen as $val) {
    echo $val, PHP_EOL;
}

echo $gen->getReturn(), PHP_EOL;

// output:
// 1
// 2
// 10

Generator delegation

Generators can now delegate to another generator, Traversable object or array automatically by using the yield from construct.

function gen()
{
    yield 1;
    yield 2;
    yield from gen2();
}

function gen2()
{
    yield 3;
    yield 4;
}

foreach (gen() as $val)
{
    echo $val, PHP_EOL;
}

Integer division with intdiv()

Integer division can be done now with the new intdiv() function and it will return integer as well.

var_dump(intdiv(10, 3)); // int(3)

Session options

session_start() now able to take array of options as an argument that override the session configuration directives, which we should have to set in the php.ini file.

session_start([
    'cache_limiter' => 'private',
    'read_and_close' => true,
]);

preg_replace_callback_array() function

preg_replace_callback_array() can take array of callbacks with the patterns. It is similar to the function preg_replace_callback() except the callbacks are executed on a per-pattern basis.

$subject = 'Aaaaaa Bbb';

preg_replace_callback_array(
    [
        '~[a]+~i' => function ($match) {
            echo strlen($match[0]), ' matches for "a" found', PHP_EOL;
        },
        '~[b]+~i' => function ($match) {
            echo strlen($match[0]), ' matches for "b" found', PHP_EOL;
        }
    ],
    $subject
);

// output:
// 6 matches for "a" found
// 3 matches for "b" found

CSPRNG Functions

This feature introduced two new functions random_int() & random_bytes() for generating cryptographically secure integers and strings.

// random_int()
var_dump(random_int(100, 999));
// output:
// int(433)

// random_bytes()
$bytes = random_bytes(5);
var_dump(bin2hex($bytes));
// output:
// string(10) "34fd44f9c4"

Nullable types

Type declaration for parameters & return values can now support null type with the help of prefexing question mark in the type name.

function test(?string $name)
{
    var_dump($name);
}

test('elePHPant'); // string(5) "elePHPant"
test(null); // NULL
test(); // Uncaught Error: Too few arguments to function test(), 0 passed in...

Void functions

A void return type has been introduced. Functions declared with void return type must either omit their return statement altogether, or use an empty return statement. NULL is not a valid return value for a void function.

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)

Symmetric array destructuring

The shorthand array syntax [] may now use as an alternative of list() function for assignments.

$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
}

Class constant visibility

Classes got constant visibility support now.

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

iterable pseudo-type

A new pseudo-type called iterable has been introduced similar to callable in scalar type declarations.

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

Multi catch exception handling

Multiple exceptions can be used now in catch block using the pipe character (|).

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

Support for keys in list()

Like the new symmetric array destructuring syntax, you can specify keys in list() or its shorthand [] syntax.

$data = [
    ["id" => 1, "name" => 'Tom'],
    ["id" => 2, "name" => 'Fred'],
];

// list() style
list("id" => $id, "name" => $name) = $data[0];

// [] style
["id" => $id, "name" => $name] = $data[0];

Support for negative string offsets

String negative offsets support has been added in PHP7, it will affects on many string manipulation functions.

var_dump("abcdef"[-2]);
var_dump(strpos("aabbcc", "b", -3));

// output:
// string (1) "e"
// int(3)

Convert callables to Closures with Closure::fromCallable()

A new static Closure::fromCallable() method has been introduced to the Closure class to allow for callables to be easily converted into Closure objects. This is because Closures are more performant to invoke than other callables, and allow for out-of-scope methods to be executed in other contexts.

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

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

$privFunc = (new Test)->exposeFunction();
$privFunc('some value');

// output:
// string(10) "some value"

References

  1. http://php.net/manual/en/migration70.new-features.php
  2. http://php.net/manual/en/migration71.new-features.php
  3. https://github.com/tpunt/PHP7-Reference