Что нового в PHP 8.2
Новый PHP 8.2 будет выпущен 24 ноября 2022 года. В этой статье мы рассмотрим все новые функции, улучшения производительности и изменения в языке и его синтаксисе.
Readonly классы
Readonly свойства были добавлены в PHP версии 8.1. Этот RFC является его продолжением, добавляет синтаксический сахар в язык для объявления всех свойств класса как readonly. Теперь вместо:
class Post
{
public function __construct(
public readonly string $title,
public readonly Author $author,
public readonly string $body,
public readonly DateTime $publishedAt,
) {}
}
Можно делать так:
readonly class Post
{
public function __construct(
public string $title,
public Author $author,
public string $body,
public DateTime $publishedAt,
) {}
}
Этот код делает то же самое если мы вручную сделаем все свойства класса как readonly; но так же при использовании readonly при объявлении класса это сделает невозможным добавление в него динамических свойств:
$post = new Post(/* … */);
$post->unknown = 'wrong';
Uncaught Error: Cannot create dynamic property Post::$unknown
Так же имейте ввиду что вы можете наследовать readonly классы только если дочерние классы так же будут отмечены как readonly.
PHP сильно изменился в последнее время и readonly классы хорошее дополнение.
Deprecate dynamic properties
Это изменение сделает PHP еще более строго типизированным но при этом может создать проблемы при миграции если разработчики обновят свои библиотеки с учетом этого нововведения. Динамические свойства объявлены как deprecated в PHP 8.2, и будут бросать исключения ErrorException в версии PHP 9.0 если свойство у класса не будет объявлено.
class Post
{
public string $title;
}
// …
$post->name = 'Name';
Магические методы __get и __set будут работать как и прежде:
class Post
{
private array $properties = [];
public function __set(string $name, mixed $value): void
{
$this->properties[$name] = $value;
}
}
// …
$post->name = 'Name';
Новое расширение random
PHP 8.2 добавляет новый генератор рандомных значений который решает множество проблем с использованием предыдущего: он более производительный, более надежный, его легче поддерживать и он не зависит от глобального состояния; устраняя много сложно отслеживаемых багов при использовании функций random в PHP.
Будет доступен новый класс Randomizer, который может принимать стратегию алгоритма. Теперь вы сможете изменить стратегию сами в зависимости от ваших потребностей. Например, на тестовом и рабочем окружении:
$rng = $is_production
? new Random\Engine\Secure()
: new Random\Engine\Mt19937(1234);
$randomizer = new Random\Randomizer($rng);
$randomizer->shuffleString('foobar');
null, true, и false как типы данных
В PHP 8.2 будут добавлены три новые типа данных, или похоже на то. Теперь во встроенных в PHP функциях теперь он будет использован как возвращаемый тип данных например в file_get_contents:
file_get_contents(/* … */): string|false
До PHP 8.2 вы уже могли использовать false вместе с другими union типами; но теперь вы можете использовать его как отдельный тип:
function alwaysFalse(): false
{
return false;
}
Disjunctive Normal Form типы
DNF типы позволяют нам объединить union
и intersection
типы, используя строгое правило: при объединении union и intersection типов, intersection типы должны быть заключены в скобки. На практике это может выглядеть примерно так:
function generateSlug((HasTitle&HasId)|null $post)
{
if ($post === null) {
return '';
}
return
strtolower($post->getTitle())
. $post->getId();
}
В этом случае, (HasTitle&HasId)|null является DNF типом данных.
Константы в трейтах
Теперь внутри трейтов можно использовать константы:
trait Foo
{
public const CONSTANT = 1;
public function bar(): int
{
return self::CONSTANT;
}
}
Вы не можете использовать эти константы напрямую по классу трейта:
trait Foo
{
public const CONSTANT = 1;
public function bar(): int
{
return Foo::CONSTANT;
}
}
Foo::CONSTANT; // ошибка
но можете через классы которые его используют:
class MyClass
{
use Foo;
}
MyClass::CONSTANT; // = 1 работает
Скрытие параметров в back traces
Теперь можно пометить свойства класса что бы их значения не отображались в логах и back traces, например значения с паролями:
function login(
string $user,
#[\SensitiveParameter] string $password
) {
// …
throw new Exception('Error');
}
login('root', 'root');
Fatal error: Uncaught Exception: Error in login.php:8
Stack trace:
#0 login.php(11): login('root', Object(SensitiveParameterValue))
#1 {main}
thrown in login.php on line 8
Изменен возвращаемый тип данных
У данных функций будут изменены сигнатуры:
DateTime::createFromImmutable()
и DateTimeImmutable::createFromMutable()
Прежде данные методы возвращали:
DateTime::createFromImmutable(): DateTime
DateTimeImmutable::createFromMutable(): DateTimeImmutable
В PHP 8.2 эти методы будут возвращать:
DateTime::createFromImmutable(): static
DateTimeImmutable::createFromMutable(): static
utf8_encode() и utf8_decode() deprecations
В PHP 8.2, использование функций utf8_encode или utf8_decode будет выдавать предупреждения:
Deprecated: Function utf8_encode() is deprecated
Deprecated: Function utf8_decode() is deprecated
Этот RFC доказывает что эти функции при их использовании могут вводить в заблуждение: эти функции конвертируют данные только между ISO-8859-1
и UTF-8
, хотя можно подумать что эти функции могут работать и с другими кодировками. Более детальное описание проблемы вы можете прочитать в RFC.
Какая альтернатива? RFC советует использовать функцию mb_convert_encoding()
.
Locale-insensitive strtolower() и strtoupper()
Обе функции теперь не чувствительны к локали. Вы можете использовать mb_strtolower
если вам нужна функция для конверсии которая учитывает locale.
Изменение сигнатур у некоторых методов из SPL
У некоторых методов из SPL были изменены сигнатуры в сторону более строгой типизации.
SplFileInfo::_bad_state_ex()
SplFileObject::getCsvControl()
SplFileObject::fflush()
SplFileObject::ftell()
SplFileObject::fgetc()
SplFileObject::fpassthru()
SplFileObject::hasChildren()
SplFileObject::getChildren()
Новый модификатор n
в PCRE
Теперь вы можете использовать модификатор n
(NO_AUTO_CAPTURE
) в pcre*
функциях.
Deprecate ${} string interpolation
В PHP возможно использовать несколько вариантов для интерполяции в строках. Этот RFC объявляет устаревшими два варианта, так как они редко используются, и часто вводят в заблуждение:
"Hello ${world}";
Deprecated: Using ${} in strings is deprecated
"Hello ${(world)}";
Deprecated: Using ${} (variable variables) in strings is deprecated
Вы по прежнему можете делать вот так:
"Hello {$world}";
"Hello $world";
Deprecate partially supported callables
Partially supported callables это функции которые могут быть вызваны используя call_user_func($callable)
, но не используя $callable()
напрямую.
"self::method"
"parent::method"
"static::method"
["self", "method"]
["parent", "method"]
["static", "method"]
["Foo", "Bar::method"]
[new Foo, "Bar::method"]
Это список всех изменений в версии PHP 8.2 на данный момент.