PHPKonf Istanbul PHP Conference 2019 - Call for Papers

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

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

Объявления скалярных типов введена в двух вариантах: принудительный (по умолчанию) и строгий. Следующие типы могут использоваться для объявления параметров (в обоих вариантах): строки (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 2 notes

up
101
PawelD
2 years 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
14
TerryE
1 year ago
$a = ''; // or 0 or false

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

$c = $a ?: 'a';
// $c is 'a'
To Top