Новая функциональность

Объявления скалярных типов

Объявления скалярных типов введена в двух вариантах: принудительный (по умолчанию) и строгий. Следующие типы могут использоваться для объявления параметров (в обоих вариантах): строки (string), целые (int), числа с плавающей точкой (float) и логические значения (bool). Они дополняют аргументы других типов, введенных в PHP 5: имена классов, интерфейсов, array и callable.

<?php
// Принудительный режим
function sumOfInts(int ...$ints)
{
    return 
array_sum($ints);
}

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

Результат выполнения данного примера:

int(9)

Для установки строгого режима, в самом начале файла необходимо поместить одну директиву declare. Это означает, что строгость объявления скалярных типов работает на уровне файла и не затрагивает весь остальной код. Эта директива затрагивает не только объявления параметров, но и возвращаемые значения функций (см. объявления возвращаемого типа), встроенные функции PHP и функции загруженных расширений.

Подробную документацию и примеры использования читайте в разделе декларация типов.

Объявления возвращаемых значений

В PHP 7 добавлена поддержка объявления возвращаемого типа. Аналогично как и объявления типов аргументов, объявление типа возвращаемого значения указывает, значение какого типа должна вернуть функция. Для объявления типа возвращаемого значения доступны все те же типы, что и для объявления типов аргументов.

<?php

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]));

Результат выполнения данного примера:

Array
(
    [0] => 6
    [1] => 15
    [2] => 24
)

Полную документацию и примеры использования читайте в разделе про объявление возвращаемого типа.

Оператор объединения с null

Был добавлен оператор объединения с null (??), являющийся синтаксическим сахаром для достаточно распространенного действия, когда совместно используются тернарный оператор и функция isset(). Он возвращает первый операнд, если он задан и не равен NULL, а в обратном случае возвращает второй операнд.

<?php
// Извлекаем значение $_GET['user'], а если оно не задано,
// то возвращаем 'nobody'
$username $_GET['user'] ?? 'nobody';
// Это идентично следующему коду:
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';

// Данный оператор можно использовать в цепочке.
// В этом примере мы сперва проверяем, задан ли $_GET['user'], если нет,
// то проверяем $_POST['user'], и если он тоже не задан, то присваеваем 'nobody'.
$username $_GET['user'] ?? $_POST['user'] ?? 'nobody';
?>

Оператор spaceship (космический корабль)

Этот оператор предназначен для сравнения двух выражений. Он возвращает -1, 0 или 1 если $a, соответственно, меньше, равно или больше чем $b. Сравнение производится в соответствии с правилами сравнения типов PHP.

<?php
// Целые числа
echo <=> 1// 0
echo <=> 2// -1
echo <=> 1// 1

// Числа с плавающей точкой
echo 1.5 <=> 1.5// 0
echo 1.5 <=> 2.5// -1
echo 2.5 <=> 1.5// 1
 
// Строки
echo "a" <=> "a"// 0
echo "a" <=> "b"// -1
echo "b" <=> "a"// 1
?>

Определение констант массивов с помощью define()

Можно определить константу типа array с помощью функции define(). В PHP 5.6 такие константы можно было задавать только с помощью const.

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

echo 
ANIMALS[1]; // выводит "cat"
?>

Анонимные классы

Была добавлена поддержка анонимных классов с помощью new class. Их можно использовать тогда, когда нужен одноразовый класс и создавать полноценный класс, а потом его объект не имеет смысла:

<?php
interface Logger {
    public function 
log(string $msg);
}

class 
Application {
    private 
$logger;

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

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

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

var_dump($app->getLogger());
?>

Результат выполнения данного примера:

object(class@anonymous)#2 (0) {
}

Подробную документацию и примеры использования читайте в разделе про анонимные классы.

Синтаксис кодирования Unicode

Он принимает шестнадцатеричный код Unicode и записываем его в формате UTF-8 в двойных кавычках или формате heredoc. Любой корректный код будет принят. Ведущие нули по желанию.

echo "\u{aa}";
echo "\u{0000aa}";
echo "\u{9999}";

Результат выполнения данного примера:

ª
ª (То же самое, что и первый вариант, но с ведущими нулями)
香

Closure::call()

Closure::call() является более производительным и коротким способом временного связывания области действия объекта с замыканием и его вызовом.

<?php
class {private $x 1;}

// До PHP 7
$getX = function() {return $this->x;};
$getXCB $getX->bindTo(new A'A'); // промежуточное замыкание
echo $getXCB();

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

Результат выполнения данного примера:

1
1

unserialize() с фильтрацией

Этот функционал обеспечивает более высокий уровень безопасности при десериализации объектов с непроверенными данными. Это позволяет предотвратить возможную инъекцию кода, позволяя разработчику использовать белый список классов для десериализации.

<?php

// Преобразование всех объектов в __PHP_Incomplete_Class
$data unserialize($foo, ["allowed_classes" => false]);

// Преобразование всех объектов, кроме MyClass и MyClass2 в __PHP_Incomplete_Class
$data unserialize($foo, ["allowed_classes" => ["MyClass""MyClass2"]]);

// Поведение по умолчанию принимает все классы (можно просто не задавать второй аргумент)
$data unserialize($foo, ["allowed_classes" => true]);

IntlChar

Новый класс IntlChar добавляет новую функциональность в ICU. Класс определяет несколько статических методов и констант для манипулирования символами Unicode.

<?php

printf
('%x'IntlChar::CODEPOINT_MAX);
echo 
IntlChar::charName('@');
var_dump(IntlChar::ispunct('!'));

Результат выполнения данного примера:

10ffff
COMMERCIAL AT
bool(true)

Для использования это класса необходимо установить расширение Intl.

Ожидания

Ожидания являются улучшенной, обратно совместимой версией старой функции assert(). Они позволяют делать предположения с нулевой стоимостью в промышленном коде и предоставляют возможность выбрасывать пользовательские исключения в случае провала ожидания.

Вместе тем, что старое API поддерживается, assert() теперь является языковой конструкцией, принимающей первым аргументом выражения, а не только строки для оценки или логические значения для проверки.

<?php
ini_set
('assert.exception'1);

class 
CustomError extends AssertionError {}

assert(false, new CustomError('Сообщение об ошибке'));
?>

Результат выполнения данного примера:

Fatal error: Uncaught CustomError: Сообщение об ошибке

Подробное описание этого функционала, а также инструкции для его конфигурирования для тестовых и промышленных сред, читайте в секции Ожидания раздела, посвященному assert().

Групповые объявления use

Классы, функции и константы импортируемые из одного и того же namespace, теперь можно группировать в одном операторе use.

<?php
// До PHP 7
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+
use some\namespace\{ClassAClassBClassC as C};
use function 
some\namespace\{fn_afn_bfn_c};
use const 
some\namespace\{ConstAConstBConstC};
?>

Выражение return в генераторах

Эта функциональность добавлена к генераторам, введенным в PHP 5.5. Она позволяет использовать оператор return в генераторах в качестве окончательного возвращаемого значения (возврат по ссылке недопустим). Это значение можно извлечь с помощью нового метода Generator::getReturn(), который можно использовать только после того, как генератор вернул все сгенерированные значение.

<?php

$gen 
= (function() {
    
yield 1;
    
yield 2;

    return 
3;
})();

foreach (
$gen as $val) {
    echo 
$valPHP_EOL;
}

echo 
$gen->getReturn(), PHP_EOL;

Результат выполнения данного примера:

1
2
3

Возможность явно получать окончательное значение генератора является очень полезной, так как позволяет клиентскому коду, использующему генератор, получать и обработать самое последнее значение генератора, после которого точно ничего больше не будет. Это сильно проще, чем вынуждать разработчика проверять, последнее ли значение вернулось и как-то по особенному его обрабатывать.

Делегация генератора

Теперь генератор может автоматически делегировать другому генератору, объекту класса, реализующий Traversable или массиву без необходимости писать в нем дополнительную обработку полученных значений. Достигается это с помощью конструкции yield from.

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

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

foreach (
gen() as $val)
{
    echo 
$valPHP_EOL;
}
?>

Результат выполнения данного примера:

1
2
3
4

Функция целочисленного деления intdiv()

Новая функция intdiv() производит целочисленное деление операндов и возвращает его результат.

<?php
var_dump
(intdiv(103));
?>

Результат выполнения данного примера:

int(3)

Опции сессий

Теперь session_start() принимает массив опций, которые переопределят конфигурационные директивы сессии установленные в php.ini.

Также опции были расширены включенной по умолчанию опцией session.lazy_write, которая говорит PHP о том, что файл сессии надо перезаписывать, только если изменились данные сессии, и опцией read_and_close, которую можно задать только через session_start() для того, чтобы PHP закрывал сессию сразу же как прочитает ее данные и не вносил в нее каких либо изменений.

К примеру, для установки session.cache_limiter равным private и немедленному закрытию сессии после чтения ее данных:

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

preg_replace_callback_array()

Новая функция preg_replace_callback_array() позволяет писать более чистый код, когда требуется использовать функцию preg_replace_callback(). До PHP 7 при необходимости обработать разные регулярные выражения разными функциями приходилось для каждой такой обработки писать отдельный вызов функции.

Теперь можно использовать одну функцию, передавая в нее ассоциативный массив, ключами которого являются регулярные выражения, а значениями - функции обратного вызова.

Функции CSPRNG

Были добавлены две новые кроссплатформенные функции для генерации криптографически безопасных строк и целых чисел: random_bytes() и random_int().

Теперь функция list() всегда может распаковывать объекты, реализующие ArrayAccess

Ранее функция list() не гарантировала корректную обработку объектов, реализующих ArrayAccess. Теперь это исправлено.

Прочие изменения

  • Добавлена возможность доступа к методам и свойствам класса при клонировании, то есть (clone $foo)->bar().
add a note add a note

User Contributed Notes 6 notes

up
97
PawelD
1 year ago
<?php
class foo { static $bar = 'baz'; }
var_dump('foo'::$bar);
?>

if < php7.0

then we will receive a syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)

but php7 returns string(3) "baz"

I think it's not documented anywhere
up
8
TerryE
10 months ago
$a = ''; // or 0 or false

$b = $a ?? 'a'; 
// $b is '' or 0 or false

$c = $a ?: 'a';
// $c is 'a'
up
-19
omarv_r at yahoo dot com
1 year ago
lexx918, It is not working unexpectedly... lets see:

Calling to isset() method for a non existing property ($foo->bar in this case), automatically the magic method __isset() is invoked. So

$a = isset($foo->bar) ?: null; // __isset

is correct.

But when we try to evaluate $foo->bar, we are calling a getter. Because the bar property does not exist, the implicit calling is to magic method __get(). So

$a = $foo->bar ?? null; // __get

is correct too.
up
-36
robert.j.pounder
10 months ago
<?php
class foo { static $bar = 'baz'; }
var_dump('foo'::$bar);

and
variations dont work

but

<?php
class foo { static $bar = 'baz'; }
$t = 'foo';
var_dump($t::$bar);

works < 7.0
up
-92
lexx918 at mail dot ru
1 year ago
Sugar of ternary operator:
<?php
$a
?? 'b'
// allegedly equivalent to
isset($a) ? $a : 'b'
?>
.. in classes working unexpectedly:
<?php
class Foo {
    public function
__get($p) { echo "__get" . PHP_EOL; }
    public function
__isset($p) { echo "__isset" . PHP_EOL; }
}
$foo = new Foo;
$a = isset($foo->bar) ?: null; // __isset
$a = $foo->bar ?? null; // __get
?>
up
-10
misvinay at gmail dot com
2 months ago
Error Handling:  In PHP 7, an exception will be thrown when a fatal and recoverable error occurs, rather than just stopping the script.

errors such as warnings and notices remain unchanged in PHP 7. Only fatal and recoverable errors throw exceptions.
To Top