Что нового в PHP 5.5

[1,3,4][2], "foobar"[2] — разыменования созданных массивов/строк

echo array(1, 2, 3)[0]; // 1
echo [1,3,4][2];        // 4
echo "foobar"[0]        // f

// это может пригодиться для быстрой генерации:
echo 'abcdefghijk'[ rand(0,10) ]; // получим одну из букв: 'abcdefghijk'

empty() — можно применять к результатам функций и выражений

Раньше empty() мог принимать только переменные, теперь можно передавать сами выражения без необходимости сохранять результат в отдельную переменную:

empty( $object->get() );

list() в foreach

В foreach стало возможным использовать list():

$array = [
	[1, 2],
	[3, 4],
];

foreach( $array as list($a, $b) ){
	echo $a;
	echo $b;
}
// получим: 1234

finally — в конструкции try/catch

Выбрасывать и ловить исключения можно с PHP 5. Такой подход позволяет контролировать выполнение кода, если есть подозрение, что в нем что-то может пойти не так.

А с версии 5.5. в эту конструкцию добавили третий блок finally. Блок finally выполняется всегда после завершается конструкции try/catch. Он выполняется даже когда код try вызвал фатальную ошибку:

try {
	echo 'Тут что-то деламе... ';
	// выбрасываем
	throw new Exception('Лови меня! ');
}
// ловим
catch( Exception $e ){
	echo $e->getMessage(); // выведет: Лови меня!
}
finally {
	echo 'А это выводиться всегда!';
}

Нужен finally для удобства, и дополнительных возможностей. С ним можно будет писать меньше кода и можно, например, удобно чистить память, когда это нужно.

Пару домонстрационных примеров:

Меньше кода

Допустим, нам нужно выполнить функцию close() в любому случае, было выброшено исключение или нет:

try {
	my_function();
}
catch( Exception $e ){
	// close(); // эта строка нужна была бы без finally
	echo $e->getMessage(); // выведет: Лови меня!
}
finally {
	close();
}
//close(); // эта строка нужна была бы без finally

Больше возможностей

Допустим мы открыли соединение с БД до выполнения кода и есть вероятность что код вызовет ошибку и открытое соединение не закроется, а нам нужно его закрыть в любом случае. finally как раз кстати:

$db = mysqli_connect();

try {
   my_function( $db ); // результат работы функции может вызвать фатальную ошибку...
}
// исключение можно не обрабатывать
finally {
   mysqli_close($db);
}

Class::class — для получение имени класса в пространствах

Появилось ключевое слово class для классов, которое выводит название класса. В обычном режиме нам это не нужно, а вот при работе с пространствами (namespace) — это удобно:

namespace test;
class A {}

echo A::class; //> test\A

yield — создание генераторов

Если говорить простым языком: yield похожа на return, она также возвращает значение, но она не обрывает работу функции, а приостанавливает её до тех пор пока не будет запрошено следующее значение. Благодаря этому создавать генераторы стало удобнее.

Пример генератора:

function generator() {
	for( $i = 1; $i <= 3; $i++ ){
		yield $i; // выброс значения
	}
}

foreach( generator() as $value ){
	echo "$value ";
}
// выведет: '1 2 3 '

Как это работает на самом деле?

yield возвращает специальный объект — Generator. Когда функция generator() вызывается в цикле, например foreach, PHP выполнит код функции до первой встречи слова yield, на котором PHP прервет работу функции, запомнит позицию и выбросит значение (объект Generator). Затем, foreach обработает значение и вызовет метод next() у полученного объекта Generator. PHP снова выполнит код функции generator(), только начнет его не с начала, а с прошлой позиции, и опять, до слова yield, которое опять выбросит объект Generator. Работа цикла прервется тогда, когда функция generator() дойдет до конца (не вернет yield), или если она будет прервана с помощью return;.

Пример передачи генератора в переменную (повторный вызов в этом случае не работает):

function generator() {
	for( $i = 1; $i <= 3; $i++ ){
		yield $i; // выброс значения
	}
}

$gen = generator();

foreach( $gen as $value ){
	echo "$value ";
}
// выведет: '1 2 3 '

// Fatal error: Uncaught Exception: Cannot traverse an already closed generator
foreach( $gen as $value ){
	echo "$value ";
}

Пример генератора который возвращает пару: ключ/значение:

function generator( $input ){
	foreach( explode('.', $input) as $part ){
		list( $num, $name ) = explode(' - ', $part );

		yield $num => trim($name);
	}
}

$input = '1 - один. 2 - два. 3 - три';

foreach( generator( $input ) as $num => $name ){
	echo "$num ($name) ";
}

Кратко о генераторах

  • Не добавляют нового функционала в язык
  • Быстрее
  • Возобновление работы генератора происходит с последнего «выброса» yield
  • В генератор можно отправлять значения и исключения (через метод throw())
  • Генераторы однонаправлены, т.е. нельзя вернуться назад
  • Меньше кода в большинстве случаев, более простые для понимания конструкции

API для хэширования паролей

Теперь PHP из коробки предлагает правильный способ хэшировать пароли. Новый API хэширования паролей предоставляет четыре функции:

  1. password_hash() — используется для хэширования пароля. В WP для этого есть своя функция wp_hash_password().

    $hash = password_hash( $passwod, PASSWORD_DEFAULT );
  2. password_verify() — используется для проверки пароля на соответствие хэшу. В WP для этого есть своя функция wp_check_password().

    if( password_verify( $password, $hash ) ){
    	// Success!
    }
  3. password_needs_rehash() — используется для проверки необходимости создать новый хэш.

  4. password_get_info() — возвращает имя алгоритма хеширования и различные параметры, используемые при хэшировании.

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