Union types
Union types are a collection of two or more types which indicate that either one of those can be used.
Note that void can never be part of a union type, since it indicates „no return value at all“.
Furthermore, nullable unions can be written using |null, or by using the existing ? notation.
public function foo(Foo|Bar $input): int|float; public function foo(Foo|null $foo): void; public function bar(?Bar $bar): void;
The nullsafe operator
Вече може да се взема първият not null резултат от повече функции.
$dateAsString = $booking->getStartDate()?->asDateTimeString();
Тук $dateAsString ще приеме стойността на втората функция, ако първата е null. Toест, все едно null coalescing operator но за функции.
Named arguments
Удобството е, че не само няма нужда да се спазва реда на аргументите, но и не е задължително всички да бъдат подавани (за такива трябва разбира се, да имаме по подразбиране null)
function foo(string $a, string $b, ?string $c = null, ?string $d = null) { /* ... */ } foo( b: 'value b', a: 'value a', d: 'value d', );
Attributes
https://lindevs.com/using-attributes-in-php-8-0
https://dev.to/icolomina/using-php-attributes-easily-2fpo
https://www.amitmerchant.com/how-to-use-php-80-attributes/
Match expression
Подобрение на добрият, стар switch оператор. Реално е syntactic sugar, но има и някои предимства:
1) може да връща резултат, който да се присвои на променлива;
2) използва стриктна проверка на типовете, т.е. 200 не е ‘200’;
3) ако няма зададен default, и не влезе в никоя от възможностите, хвърля UnhandledMatchError exception;
Общо взето, основното му предимство е, че е по-стриктно откъм типове.
Constructor property promotion
Syntactic sugar. Цялата му философия се вижда от долният пример. Да не трябва да декларираш отделно клас пропъртитата, които сетваш в конструктора, а да става наведнъж – в конструктора.
In short: property promotion allows you to combine class fields, constructor definition and variable assignments all into one syntax, in the construct parameter list.
class Money { public function __construct( public Currency $currency, public int $amount, ) {} }
Важно е, че constructor property promotion НЕ е разрешено за абстрактни класове и интерфейси, но са разрешени за traits.
Също, НЕ са разрeшени т.н. „Variadic Parameters Are Not Allowed“ например:
class TestClass
{
// Error: Variadic parameter
public function __construct(public string ...$strings)
{
//...}
}
New static
return type
New mixed
type for both parameter and return type
Throw expression
Изключенията вече могат да се присвояват на променливи.
$triggerError = fn () => throw new MyError(); $foo = $bar['offset'] ?? throw new OffsetDoesNotExist('offset');
Inheritance with private methods
Досега PHP правеше проверка за signature както на public и protected методите, но така и на private, което e безсмислено и има RFC това да бъде премахнато.
Private методите няма смисъл да се декларират като final, защото те така или иначе не могат да се наследяват. Вече ще дава:
Warning: Private methods cannot be final as they are never overridden by other classes
Weak maps
SplObjectStorage е механизъм, с чиято помощ може да се създават колекции от обекти, като масиви, в които ключът е самият обект и евентуално може да има стойност, може и да няма. Системен клас, който си идва с набор от методи за управление на всичко това.
И като добавиш готов обект с метода attach(object $obj, mixed $value = null): void вече имаш рефърънс към този обект. И ако унищожиш този обект, например с unset($obj1), той ще е NULL но в SplObjectStorage ще съществува, което си е memory leak.
$obj1 = new stdClass(); $obj1->name = 'Foo'; $obj1->age = 28; $map = new SplObjectStorage(); $map[$obj1] = 'Additional data for bla bla bla...'; var_dump($map->current()); // имаме си го unset($obj1); // Only clears reference var_dump($obj1); // NULL echo count($map); // 1 var_dump($map->current()); // имаме си го пак, нищо че оригиналът е ънсетнат
При WeakMap – не, изтрива се и от там, което е предимство откъм памет.
Демек:
$obj1 = new stdClass(); $obj1->name = 'Foo'; $obj1->age = 28; $map = new WeakMap(); $map[$obj1] = 'Additional data for бла бла бла...'; var_dump($map->offsetGet($obj1)); // имаме си го unset($obj1); // Removes $obj and the key and value from $map as well. var_dump($obj1); // NULL echo count($map); // 0 var_dump($map->offsetGet($obj1)); // нямаме си го, garbage collector го е забърсал
Иначе трябва изрично да изчистваш реферънса в SplObjectStorage с SplObjectStorage::detach(object $object
): void
Allowing ::class
on objects
За да вземеш класа на обект, вече не ти трябва get_class(). Може и с $foo::class
Non-capturing catches
Вече няма нужда в catch() да се задава променлива, ако не ти трябва.
try { // Something goes wrong } catch (MySpecialException) { // Do something here }
Trailing comma in parameter lists
Вече може да имаш запетая след последният параметър.
function patapan(string $parameterA, int $parameterB, Foo $objectfoo, )
{
//...}
Create DateTime
objects from interface
New Stringable
interface
Вграден интерфейс, който може да се използва като typehint за да зададе, че очакваната променлива например, трябва да може да се използва като string. Пък била тя string или обект с __toString() метод, който може да се използва като стринг.
function bar(string|Stringable $stringable) { /* ... */ } bar(new Foo()); bar('abc');
Вижда се, че на bar() можем да подадем както string скаларна променлива, така и обект, съдържащ __toString() магичн метод.
От примера се вижда, че е напълно нормално двата typehints да се използват заедно като uniontype.
New str_contains()
function
Whether a string contains another string…
if (str_contains('string with lots of words', 'words')) { /* ... */ }
New str_starts_with()
and str_ends_with()
functions
str_starts_with('haystack', 'hay'); // true str_ends_with('haystack', 'stack'); // true
New fdiv()
function
var_dump(fdiv(5.7, 1.3)); // float(4.384615384615385) var_dump(fdiv(4, 2)); // float(2) var_dump(fdiv(1.0, 0.0)); // float(INF) var_dump(fdiv(-1.0, 0.0)); // float(-INF) var_dump(fdiv(0.0, 0.0)); // float(NAN)
New get_debug_type()
function
По-удобна версия на gettype(), която например дава името на класа и т.н…
Type | Example value | gettype() | get_debug_type() |
---|---|---|---|
Class object | new stdClass() | object | stdClass |
Class object | new DateTime() | object | DateTime |
Class object | new Foo\Bar() | object | Foo\Bar |
Closure | function() {} | object | Closure |
Anonymous class | new class {} | object | class@anonymous |
Anonymous subclass | new class extends Foo{} | object | Foo@anonymous |
New get_resource_id()
function
Всяка ресурс променлива (разни хендлъри към бази данни…) имат ID, което до сега се вземаше като се тайпкастне ресурса към int.
Сега има тази специална функция.
Abstract methods in traits improvements
Трейтовете могат да декларират абстрактни методи, като е важно да се спомене, че спазванео на сигнъчъра е задължителен.
Object implementation of token_get_all()
Variable syntax tweaks
Type annotations for internal functions
Литература:
https://stitcher.io/blog/new-in-php-8#new-features
https://php.watch/articles/practical-weakmap