Скалярные типы объявляют в двух режимах: нестрогом, в котором PHP работает по умолчанию, и строгом. Теперь как в нестрогом, так и в строгом режимах разрешается задавать следующие типы параметров: строки (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 (??
), являющийся
синтаксическим сахаром для достаточно распространённого действия, когда совместно
используются тернарный оператор и функция 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';
?>
Этот оператор предназначен для сравнения двух выражений. Он возвращает -1, 0 или 1 если $a, соответственно, меньше, равно или больше чем $b. Сравнение производится в соответствии с правилами сравнения типов PHP.
<?php
// Целые числа
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 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
?>
Можно определить константу типа 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) { }
Подробную документацию и примеры использования читайте в разделе про анонимные классы.
Синтаксис принимает кодовую точку Юникода в шестнадцатеричном формате, которую записали в кодировке UTF-8 как строку в двойных кавычках или heredoc-синтаксисом, и выводит эту кодовую точку в формате UTF-8. Синтаксис примет каждую допустимую кодовую точку. Ведущие нули в шестнадцатеричной последовательности указывать необязательно.
<?php
echo "\u{aa}", PHP_EOL;
echo "\u{0000aa}", PHP_EOL;
echo "\u{9999}", PHP_EOL;
echo <<<EOT
\u{01f418}
EOT;
?>
Результат выполнения приведённого примера:
ª ª (То же, что и первый вариант, но с ведущими нулями) 香
Closure::call() — более производительный и короткий способ временного связывания области действия объекта с замыканием и его вызовом.
<?php
class A
{
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
Эта функциональность обеспечивает более высокий уровень безопасности при десериализации объектов с непроверенными данными. Это позволяет предотвратить возможную инъекцию кода, позволяя разработчику использовать белый список классов для десериализации.
<?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 добавляет новую функциональность в ICU. Класс определяет несколько статических методов и констант для манипулирования символами Unicode.
<?php
printf('%x', IntlChar::CODEPOINT_MAX);
echo IntlChar::charName('@');
var_dump(IntlChar::ispunct('!'));
?>
Результат выполнения приведённого примера:
10ffff COMMERCIAL AT bool(true)
Для работы с этим классом требуется установить модуль Intl.
Ожидания являются улучшенной, обратно совместимой версией старой функции assert(). Они позволяют делать предположения с нулевой стоимостью в промышленном коде и предоставляют возможность выбрасывать пользовательские исключения в случае провала ожидания.
Вместе тем, что старое API поддерживается, assert() теперь является языковой конструкцией, принимающей первым аргументом выражения, а не только строки (string) для оценки или логические значения (bool) для проверки.
<?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\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};
?>
Эта функциональность добавлена к генераторам, введённым в PHP 5.5.
Она позволяет использовать оператор return
в генераторах в качестве
окончательного возвращаемого значения (возврат по ссылке недопустим). Это значение можно
извлечь с помощью нового метода Generator::getReturn()
, который можно
использовать только после того, как генератор вернул все сгенерированные значение.
<?php
$gen = (function() {
yield 1;
yield 2;
return 3;
})();
foreach ($gen as $val) {
echo $val, PHP_EOL;
}
echo $gen->getReturn(), PHP_EOL;
?>
Результат выполнения приведённого примера:
1 2 3
Явно получать конечное значение генератора полезно, поскольку разрешает клиентскому коду, который запустил генератор, получать и обрабатывать финальное значение генератора (возможно, из какой-то формы сопрограммных вычислений). Это значительно проще, чем заставлять клиентский код проверять, последнее ли значение вернул генератор, а затем, если это так, отдельно обрабатывать значение.
Теперь генераторы за счёт конструкции yield from
умеют автоматически делегировать
выдачу значений другому генератору, Traversable-объекту
или массиву без написания шаблонного кода во внешнем генераторе.
<?php
function gen()
{
yield 1;
yield 2;
yield from gen2();
}
function gen2()
{
yield 3;
yield 4;
}
foreach (gen() as $val)
{
echo $val, PHP_EOL;
}
?>
Результат выполнения приведённого примера:
1 2 3 4
Новая функция intdiv() выполняет целочисленное деление операндов и возвращает результат деления.
<?php
var_dump(intdiv(10, 3));
?>
Результат выполнения приведённого примера:
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(). До PHP 7 при обработке отдельных регулярных выражений отдельными функциями приходилось для каждой такой обработки писать отдельный вызов функции.
Теперь можно использовать одну функцию и передавать в неё ассоциативный массив, в котором ключи — регулярные выражения, а значения — функции обратного вызова.
Добавили две новые кросс-платформенные функции для генерации криптографически безопасных строк и целых чисел: random_bytes() и random_int().
Раньше функция list() не гарантировала корректную обработку объектов, которые реализуют интерфейс ArrayAccess. Это исправили.
(clone $foo)->bar()
.