ИТ Блог. Администрирование серверов на основе Linux (Ubuntu, Debian, CentOS, openSUSE)

Что нового в PHP 8 (функции, улучшения и JIT-компилятор). Часть 3

Что нового в PHP 8 (функции, улучшения и JIT-компилятор)

Слабые карты

Слабая карта – это набор данных (объектов), на которые слабо ссылаются ключи, это означает, что они не защищены от сбора мусора.

В PHP 7.4 добавлена поддержка слабых ссылок для сохранения ссылки на объект, которая не препятствует уничтожению самого объекта.

Как отметил Никита Попов:

«Сырые слабые ссылки имеют лишь ограниченную полезность, а слабые карты гораздо чаще используются на практике. Невозможно реализовать эффективную слабую карту поверх слабых ссылок PHP, потому что возможность регистрации обратного вызова уничтожения не предоставляется».

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

В длительных процессах это предотвратит утечки памяти и улучшит производительность. Смотрите следующий пример из RFC:

$map = new WeakMap;
$obj = new stdClass;
$map[$obj] = 42;
var_dump($map);

 

В PHP 8 приведенный выше код даст следующий результат:

object(WeakMap)#1 (1) {
	[0]=>
	array(2) {
		["key"]=>
		object(stdClass)#2 (0) {
		}
		["value"]=>
		int(42)
	}
}

 

Если вы сбросили объект, ключ автоматически удаляется со слабой карты:

unset($obj);
var_dump($map);

 

Теперь результат будет следующим:

object(WeakMap)#1 (0) {
}

 

Завершающая запятая в списке параметров

Конечные запятые – это запятые, добавляемые к спискам элементов в разных контекстах. В PHP 7.2 введены запятые в синтаксисе списка, в PHP 7.3 введены запятые в вызовах функций.

PHP 8 теперь вводит запятые в списках параметров с функциями, методами и замыканиями, как показано в следующем примере:

class Foo {
	public function __construct(
		string $x,
		int $y,
		float $z, // trailing comma
	) {
		// do something
	}
}

 

Разрешить класс синтаксиса :: на объектах

Чтобы получить имя класса, мы можем использовать синтаксис FooBar::class. RFC предлагает распространить тот же синтаксис на объекты, чтобы теперь можно было извлечь имя класса данного объекта, как показано в примере ниже:

$object = new stdClass;
var_dump($object::class); // "stdClass"
 
$object = null;
var_dump($object::class); // TypeError

 

С PHP 8, $object::class обеспечивает тот же результат, что и get_class($object). Если $object не является объектом, он генерирует исключение TypeError.

 

Атрибуты v2

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

До PHP 7.4 комментарии к документам были единственным способом добавления метаданных к объявлениям классов, функций и т. д. Теперь в Atcributes v2 RFC представлены атрибуты для PHP, определяющие их как форму структурированных синтаксических метаданных, которые можно добавлять в объявления классы, свойства, функции, методы, параметры и константы.

Атрибуты добавляются перед объявлениями, на которые они ссылаются. Смотрите следующие примеры из RFC:

<<ExampleAttribute>>
class Foo
{
	<<ExampleAttribute>>
	public const FOO = 'foo';

	<<ExampleAttribute>>
	public $x;

	<<ExampleAttribute>>
	public function foo(<<ExampleAttribute>> $bar) { }
}

$object = new <<ExampleAttribute>> class () { };

<<ExampleAttribute>>
function f1() { }

$f2 = <<ExampleAttribute>> function () { };

$f3 = <<ExampleAttribute>> fn () => 1;

 

Атрибуты могут быть добавлены до или после комментария блока документов:

<<ExampleAttribute>>
/** docblock */
<<AnotherExampleAttribute>>
function foo() {}

 

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

<<WithoutArgument>>
<<SingleArgument(0)>>
<<FewArguments('Hello', 'World')>>
function foo() {}

 

Посмотрите RFC для более глубокого обзора атрибутов PHP, вариантов использования и альтернативного синтаксиса. Обратите внимание, что Атрибуты v2 в настоящее время ожидают реализации.

 

Новые функции PHP

PHP 8 приносит несколько новых функций в язык:

  1. str_contains
  2. str_starts_with () и str_ends_with ()
  3. get_debug_type

 

str_contains

До PHP 8, strstr и strpos были типичными вариантами для разработчиков для поиска подстроки внутри заданной строки. Проблема в том, что обе функции не считаются интуитивно понятными, и их использование может сбивать с толку новых разработчиков PHP. Смотрите следующий пример:

$mystring = 'Managed WordPress Hosting';
$findme = 'WordPress';
$pos = strpos($mystring, $findme);

if ($pos !== false) {
	echo "Строка найдена";
} else {
	echo "Строка не найдена";
}

 

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

«Эта функция может возвращать логическое значение FALSE, но также может возвращать и не булево значение, которое оценивается как FALSE . […] Используйте оператор === для проверки возвращаемого значения этой функции».

 

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

Теперь RFC предлагает введение новой функции, позволяющей искать внутри строки: str_contains.

str_contains ( string $haystack, string $needle ) : bool

 

Его использование довольно просто, str_contains проверяет в $needle найден ли $haystack и возвращается true или false соответственно.

Итак, благодаря str_contains, мы можем написать следующий код:

$mystring = 'Managed WordPress Hosting';
$findme   = 'WordPress';

if (str_contains($mystring, $findme)) {
	echo "Строка была найдена";
} else {
	echo "Строка не найдена";
}

 

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

 

str_starts_with() и str_ends_with()

В дополнение к функции str_contains, две новые функции позволяют искать значение needle внутри заданной строки: str_starts_withи str_ends_with.

Эти новые функции проверяют, начинается или заканчивается ли данная строка другой строкой:

str_starts_with (string $haystack, string $needle) : bool
str_ends_with (string $haystack, string $needle) : bool

 

Обе функции возвращают false если $needle длиннее $haystack.

Согласно Уиллу Хаджинсу, автору RFC:

«Функциональность str_starts_with и str_ends_with настолько необходима, что ее поддерживают многие основные PHP-фреймворки, включая Symfony, Laravel, Yii, FuelPHP и Phalcon».

Благодаря им, мы теперь можем избежать использования субоптимальных и менее интуитивные функций, такие как substr, strpos. Обе функции чувствительны к регистру:

$str = "WordPress";
if (str_starts_with($str, "Word")) echo "Найдено!";

if (str_starts_with($str, "word")) echo "Не найдено!";

 

get_debug_type

get_debug_type это новая функция PHP, которая возвращает тип переменной. Новая функция работает почти так же, как и функция gettype, но get_debug_type возвращает имена собственных типов и разрешает имена классов.

Это хорошее улучшение для языка, так как gettype() не полезно для проверки типов.

RFC предоставляет два полезных примера, чтобы лучше понять разницу между новой функцией  get_debug_type() и gettype(). Первый пример показывает gettype на примере:

$bar = [1,2,3];

if (!($bar instanceof Foo)) { 
	throw new TypeError('Expected ' . Foo::class . ', got ' . (is_object($bar) ? get_class($bar) : gettype($bar)));
}

 

В PHP 8 мы могли бы использовать get_debug_type вместо выше указанного:

if (!($bar instanceof Foo)) { 
	throw new TypeError('Expected ' . Foo::class . ' got ' . get_debug_type($bar));
}

 

Следующая таблица показывает возвращаемые значения get_debug_type и gettype:

Значение gettype() get_debug_type()
1 integer int
0.1 double float
true boolean bool
false boolean bool
null NULL null
“WordPress” string string
[1,2,3] array array
A class with name “Foo\Bar” object Foo\Bar
An anonymous class object class@anonymous


Дополнительные RFC

На момент написания этой статьи несколько RFC, предназначенных для PHP 8, все еще находятся в стадии разработки и/или ожидают реализации. Мы добавим их, как только их статус изменится на «Выполнено».

Вот краткий список дополнительных одобренных улучшений, которые будут частью PHP 8:

  1. Интерфейс Stringable: RFC представляет интерфейс Stringable, который автоматически добавляется в классы, реализующие метод __to String(). Основная цель здесь – использовать тип объединения string|Stringable.
  2. Новые API DOM Living Standard в ext/dom: RFC предлагает реализовать текущий стандарт DOM Living Standard для расширения PHP DOM путем введения новых интерфейсов и общедоступных свойств.
  3. Статический тип возврата: PHP 8 вводит использование в качестве типа static возвращаемого ряда типов self и parent.
  4. Изменения синтаксиса переменных: RFC устраняет некоторые остаточные несоответствия в синтаксисе переменных PHP.
PHP 8 выйдет позже в этом году, и он принесет много изменений и улучшений.

Резюме

В этой серии статей мы рассмотрели все ключевые изменения и улучшения, ожидаемые с выпуском PHP 8. Самым ожидаемым из них, безусловно, является компилятор Just in Time, но с PHP 8 появилось намного больше.

Теперь ваша очередь: готовы ли вы протестировать предстоящие функции PHP? Какой из них ваш любимый? Оставьте свое мнение в разделе комментариев ниже.

 

Начало:

Exit mobile version