Что нового в PHP 7.1

?string — Обнуляемый тип (и null тип)

Типы для параметров и возвращаемых значений могут быть помечены как обнуляемые путем добавления префикса в виде знака вопроса. Это означает, что указанные параметры и возвращаемые значения, могут быть как указанного типа, так и NULL.

function testReturn(): ?string {
	return 'elePHPant';
}

var_dump( testReturn() ); // string(10) "elePHPant"

function testReturn(): ?string {
	return null;
}

var_dump( testReturn() ); // NULL

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

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

void — возвращаемый тип

Теперь функции и методы, которые не должны ничего возвращать, можно помечать возвращаемым типом void. Оператор return при этом должен отсутствовать или должен быть пустым - return;. Вызов return null; вызовет ошибку.

function someMethod(): void {
	// работает если return отсутствует
	// работает с return;
	// не работает если return null;
	// не работает если return 123;
}

['key'=>$var] = ['key'=>'Значение'] — Деструктурирование массивов

Wiki: Destructuring assignment from an array to variables (short list syntax).

Можно использовать синтаксис [] = [] для деструктуризации массивов и присвоения значений массива переменным - альтернатива функции list().

Пример с индексным массивом:

list( $one, $two ) = [ 'один', 'два' ]; // list style

[ $one, $two ] = [ 'один', 'два' ];     // [] style

echo "$one, $two"; //> один, два

Тоже самое можно сделать и с ассоциативным массивом, извлекая из них значения по ключам. Имена получаемых могут быть любыми, главное — совпадение по ключам.

$person = [ 'first' => 'Rasmus', 'last' => 'Lerdorf', 'manager' => true ];

// Порядок извлечения не важен
[ 'last' => $lastname, 'first' => $firstname ] = $person;

echo "$lastname, $firstname"; //> Lerdorf, Rasmus

Вложенная деструктуризация. Также можно присвоить значения вложенных массивов:

[ [$a, $b], [$c, $d] ] = [ [1, 2], [3, 4] ];
$options = [ 'enabled' => true, 'compression' => ['algo' => 'gzip'] ];

[
	'enabled' => $enabled,
	'compression' => [
		'algo' => $algo,
	]
] = $options;

Деструктуризация в foreach.

Синтаксис list() разрешен не только в левой части операции присваивания, но и в качестве переменной в цикле foreach. Новый синтаксис [] так же работает в этом случае:

$persons = [
	[ 'first' => 'Rasmus', 'last' => 'Lerdorf' ],
	[ 'first' => 'Egor',   'last' => 'Drujo' ],
	[ 'first' => 'Telia',  'last' => 'Masterok' ],
];

foreach( $persons as [ 'first' => $first, 'last' => $last ] ){

	echo "$first, $last";
}

list( 'id'=>$id ) = $data — поддержка ключей в list()

Теперь оператор list() поддерживает ключи. Это позволяет деструктурировать массивы с нечисловыми или непоследовательными ключами.

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

// стиль list()
list("id" => $id1, "name" => $name1) = $data[0];

// стиль []
[ "id" => $id1, "name" => $name1 ] = $data[0];

// стиль list()
foreach ( $data as list("id" => $id, "name" => $name) ) {
	// logic here with $id and $name
}

// стиль []
foreach ( $data as ["id" => $id, "name" => $name] ) {
	// logic here with $id and $name
}

Closure::fromCallable() — новый статический метод Closure

В класс Closure добавлен новый статический метод для возможности легко преобразовать callable в объекты типа Closure.

class Test {

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

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

}

$privFunc = (new Test)->exposeFunction();

$privFunc('значение'); //> string(16) "значение"

private const — Область видимости констант в классах

Конец публичным константам, теперь для констант можно указать видимость:

class ConstClass {
	const CONST_ONE = 1; // public
	public const CONST_TWO = 2;
	protected const CONST_THREE = 3;
	private const CONST_FOUR = 4;
}

iterable — новый псевдо-тип

Wiki: RFC: Iterable

Введен новый тип iterable для передаваемых/возвращаемых значений. Может использоваться при передаче массивов или объектов, которые соответствуют интерфейсу Traversable.

function myfunc( iterable $data ){
	foreach( $data as $k => $v ){
		echo $k, ':', $v, PHP_EOL;
	}
}

// массив
myfunc([10, 20, 30]); // 0:10 1:20 2:30

// объект
myfunc( new SplFixedArray(3) ) // 0: 1: 2:

// генератор
function myGen(){
	yield 10;
	yield 20;
	yield 30;
}
myfunc( myGen() ); // 0:10 1:20 2:30

?int = null — тип передаваемых/возвращаемых значений

Wiki: Nullable Types

В PHP 7.0 стало возможным указать тип возвращаемых/передаваемых значений, но типизация не допускала использование null в качестве значения параметра.

В PHP 7.1 для разрешения null перед типом параметра указывается ?:

function myfunc( ?int $i ) : ?int {
  var_dump($a);
  return $a;
}

myfunc( 20 );   // int(20)
myfunc( null ); // null
myfunc();       // Ошибка: Uncaught Error: Too few arguments to function name(), 0 passed

$string[-1] — отрицательное значение смещения в строках

Добавлена возможность использовать отрицательное значение для смещения в строках

echo $string[-1]; // последний символ

catch (First | Second $e) — обработка нескольких исключений в одном блоке catch

В блоке catch теперь можно обрабатывать несколько исключений, перечисляя их через символ вертикальной черты (|). Это может быть полезно, если различные исключения обрабатываются одинаково.

try {
	// Какой то код
}
catch ( FirstException | SecondException $e ) {
	// Обрабатываем оба исключения
}

Заметки по PHP 7.1

PHP движется в сторону строгой типизации данных и при переходе на 7.1 я столкнулся с ФАТАЛЬНОЙ ошибкой. И мне это показалось очень странным. Приведу пример:

$foo = '';

$foo['bar'] = 'мир';   // Warning: Illegal string offset 'bar'

$foo['bar'][] = 'мир'; // Fatal error: Uncaught Error: Cannot use string offset as an array
					   // фатальная ошибка: нельзя использовать отступ строки как массив...

При Warning PHP еще работает, а дальше уже нет! А еще в 7.0 код просто работал, даже без предупреждений и нотисов... Похоже на недоработку в PHP 7.1.

Эта заметка встроена в: PHP 5.3 - 8.2 — Синтаксис, Новинки