Продължете към съдържанието
Начало » Блог » PHP 8.6

PHP 8.6

За разлика от PHP 8.5, която донесе големи езикови промени като |>, URI extension и clone with, PHP 8.6 изглежда е по-скоро еволюционно издание с множество подобрения в езика, типовата система, стандартните функции и производителността.

По-интересните нововъведения в PHP 8.6

Новост Какво дава
Подобрения при типовете По-строго и последователно поведение на типовете
Подобрения на attributes Повече възможности за работа с метаданни
Подобрения при generics-подобни конструкции По-добра работа на статичните анализатори
Нови/подобрени функции Допълнителни функции в стандартната библиотека
Подобрения на DOM По-добра работа с HTML/XML
Подобрения на Date/Time Допълнителни възможности и корекции
Подобрения на PHP engine Оптимизации на изпълнението
Подобрения на JIT Оптимизации за определени натоварвания
Подобрения на Fibers По-стабилна работа с асинхронни/кооперативни конструкции
Подобрения на OpenSSL/cryptography По-добра съвместимост със съвременни криптографски библиотеки

Важно е обаче да не се смесват RFC предложенията за PHP 8.6 с вече приетите промени. Тъй като версията още е Beta, окончателният списък трябва да се гледа в NEWS и UPGRADING на самия release.

PHP 8.6 — пълен практически преглед

1. clamp() — нова стандартна функция

Една от най-практичните нови функции.

clamp() гарантира, че дадена стойност е в определен диапазон.

Преди

$value = max(0, min(100, $value));

или:

$value = $value < 0 ? 0 : ($value > 100 ? 100 : $value);

PHP 8.6

$value = clamp($value, 0, 100);

Примери:

clamp(50, 0, 100);   // 50clamp(-10, 0, 100);  // 0clamp(150, 0, 100);  // 100

Функцията проверява и невалидни граници и има дефинирано поведение при NAN. RFC-ът вече е имплементиран в PHP 8.6.

Практическа употреба:

$discount = clamp($discount, 0, 50);$quantity = clamp($quantity, 1, 100);$rating = clamp($rating, 1, 5);

2. #[\Override] вече работи и върху class constants

Това е логично продължение на #[Override].

В PHP 8.3 атрибутът беше добавен за методи, а в PHP 8.5 — за properties. PHP 8.6 го разширява и към class constants.

Преди

class Base{    public const VERSION = 1;}class Child extends Base{    public const VERSION = 2;}

От кода не е очевидно дали:

VERSION

умишлено override-ва родителската константа или просто има същото име.

PHP 8.6

class Base{    public const VERSION = 1;}class Child extends Base{    #[\Override]    public const VERSION = 2;}

Ако няма какво да бъде override-нато:

class Child{    #[\Override]    public const VERSION = 2;}

PHP ще генерира грешка.

Това е особено полезно за големи codebase-и и framework-и.


3. ReflectionProperty isReadable() и isWritable()

PHP 8.6 добавя два много полезни метода:

ReflectionProperty::isReadable()
ReflectionProperty::isWritable()

Те решават проблем, който стана по-сложен след въвеждането на readonly properties и asymmetric visibility в PHP 8.4.

Преди

Трябваше да анализирате комбинация от:

$property->isPublic();
$property->isPrivate();
$property->isProtected();
$property->isReadOnly();

а при asymmetric visibility логиката става още по-сложна.

PHP 8.6

$reflection = new ReflectionClass(User::class);$property = $reflection->getProperty('email');if ($property->isReadable()) {    // може да бъде прочетено}if ($property->isWritable()) {    // може да бъде записано}

Това е особено полезно за:

  • ORM;
  • serializer-и;
  • dependency injection;
  • form libraries;
  • API mapper-и;
  • автоматично генериране на документация.

4. __debugInfo() вече е позволен в enum

Преди enum не можеше да дефинира __debugInfo().

PHP 8.6 премахва това ограничение. RFC-ът е имплементиран.

Преди

enum Status: string{    case ACTIVE = 'active';    public function __debugInfo(): array    {        return [            'status' => $this->value        ];    }}

Това не беше позволено.

PHP 8.6

enum Status: string{    case ACTIVE = 'active';    public function __debugInfo(): array    {        return [            'status' => $this->value        ];    }}

Сега:

var_dump(Status::ACTIVE);

може да предостави контролирано debug представяне.


5. Оптимизация на closures

Това е промяна, която няма да променя кода, но може да подобри производителността.

RFC-ът въвежда две оптимизации.

5.1. PHP може автоматично да направи closure-а static

Имаме:

class UserService{    public function getNames(array $users): array    {        return array_map(            function ($user) {                return $user['name'];            },            $users        );    }}

Closure-ът не използва $this.

PHP 8.6 може вътрешно да го третира като static.

Еквивалентът концептуално е:

static function ($user) {    return $user['name'];}

Това позволява оптимизация на closure-а.


5.2. Stateless closures могат да бъдат кеширани

Например:

array_map(    static fn($x) => $x * 2,    $numbers);

Closure-ите, които:

  • са static;
  • не capture-ват променливи;
  • нямат static variables;

могат да бъдат кеширани между употребите.

Това е особено интересно при код, който генерира много closures.


6. По-сигурни default настройки за sessions

Това е една от по-важните промени за production приложения.

RFC-ът за secure session defaults променя няколко настройки по подразбиране.

session.use_strict_mode

Преди

session.use_strict_mode=0

PHP 8.6

session.use_strict_mode=1

Това предотвратява приемането на произволни session IDs, предоставени от клиента.


session.cookie_httponly

Session cookie вече трябва да бъде защитена срещу достъп през JavaScript.

Концептуално:

session.cookie_httponly=1

Така:

document.cookie

не може да прочете session cookie.


session.cookie_samesite

Целта е по-сигурно поведение при cross-site заявки.

Това е значимо за приложения с:

  • login;
  • административни панели;
  • cookies;
  • CSRF защита;
  • payment системи.

За ново PHP приложение това означава по-добра сигурност без да трябва изрично да се конфигурира всяка настройка от нулата.


7. mb_ereg*() / mbregex са deprecated

Това е важно при стари PHP приложения.

Oniguruma, библиотеката, използвана от PHP за mbregex, вече не се поддържа upstream.

Затова PHP 8.6 започва процеса:

PHP 8.6 → deprecated

PHP 9.0 → removal

RFC-ът е имплементиран.

Засегнати са например:

mb_ereg(), mb_ereg_match(), mb_ereg_replace(), mb_ereg_replace_callback(), mb_ereg_search(), mb_ereg_search_getpos(), mb_ereg_search_getregs(), mb_ereg_search_init(), mb_ereg_search_pos(), mb_ereg_search_regs(), mb_ereg_search_setpos(), mb_eregi(), mb_eregi_replace(), mb_regex_encoding(), mb_regex_set_options(), mb_split()

Преди

$result = mb_ereg_replace(    '[0-9]+',    '',    $text);

PHP 8.6

Получавате deprecation warning.

В много случаи трябва да преминете към PCRE:

$result = preg_replace(    '/[0-9]+/u',    '',    $text);

Това е едно от нещата, които трябва да се проверят първо при миграция на стар PHP проект към 8.6.


8. Ограничаване на прекалено много stream filters

PHP 8.6 въвежда защита срещу злоупотреба с голям брой stream filters.

При използване на повече от 16 filters се предвижда deprecation warning. RFC-ът е насочен към защита от атаки чрез filter chains.

Потенциално проблемен стар код

$stream = fopen($file, 'r');for ($i = 0; $i < 100; $i++) {    stream_filter_append(        $stream,        'convert.base64-decode'    );}

PHP 8.6 започва да ограничава такива конструкции.

Ако реално имате нужда от повече filters, RFC-ът предвижда настройка:

filter.max_filter_count

Това е предимно security hardening и вероятно няма да засегне нормалните приложения.


9. По-безопасни persistent MySQL connections

Това е особено интересно за PHP + MySQL приложения.

RFC за минималните поддържани версии на PHP 8.6 предвижда използване на:

COM_RESET_CONNECTION

при persistent connections.

Минималните версии, предложени за тази функционалност, са:

MySQL    5.7.3+MariaDB  10.2.4+

Целта е persistent connection да бъде върната в чисто състояние между заявките.

Това е важно, защото при persistent connection не искате:

Request A   ↓connection state   ↓Request B

да наследява неочаквано състояние от предишната заявка.