PHP 7.4: Основни нововъведения
PHP 7.4 е последният минорен 7.x преди линията 8.0: добавя типизирани свойства, arrow functions, ограничена ковариантност/контравариантност и ежедневен синтактичен захар (??=, spread в масиви, разделители в числа). На паралелна писта идват FFI, OPcache preloading и модерният чифт __serialize / __unserialize. При миграция фокусирайте се върху: инициализация на typed properties, константи за password алгоритми (вече низове), build/разширения (SQLite/Zip вече не са банднати, преход към pkg-config).
Съдържание
- Типизирани свойства
- Arrow functions
- Ковариантност и контравариантност
- Присвояване с null coalescing (
??=) - Spread оператор в масиви
- Разделител в числови литерали
- Слаби референции (WeakReference)
- Изключения от
__toString() - Сериализация:
__serialize/__unserialize - Разширения и стандартна библиотека
- Практични рецепти
- Обратно несъвместими промени (миграционни бележки)
- Deprecated (поправете рано)
- Други промени и експлоатация (build, INI, perf)
Типизирани свойства
Свойствата на клас могат да имат типове. Неинициализирано typed property не трябва да се чете преди присвояване — идва Typed property ... must not be accessed before initialization.
final class User
{
public int $id;
public string $name;
public ?string $nickname = null;
}
От практиката:
- Ако „няма стойност“ е валидно — ползвайте
?Typeили default. - Тип
callableза property не се поддържа. - Обектните typed properties имат ограничения при декларация — вижте мануала.
Arrow functions
fn улавя променливи от обкръжението по стойност и връща един израз — удобно за кратки callback-и.
$factor = 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3]);
fn е запазена дума — не може име на функция/клас (методи/константи — ок).
Ковариантност и контравариантност
Типовете на връщане могат да се стесняват, типовете на параметрите — да се разширяват при наследяване, с ограничения. Пълна вариантност работи най-добре с autoload; в един файл са позволени само нециклични препратки към класове.
Присвояване с null coalescing (??=)
Присвоява се, ако отляво е unset или null:
$config['debug'] ??= false;
Spread оператор в масиви
Разпаковане на итерируеми стойности в литерал:
$base = [1, 2];
$all = [0, ...$base, 3]; // [0, 1, 2, 3]
Комбинира се с array_merge(...$arrays); array_merge() без аргументи връща [].
Разделител в числови литерали
Подчертаванията подобряват четимостта, не променят стойността:
$million = 1_000_000;
$hex = 0xFF_FF_FF;
Слаби референции (WeakReference)
WeakReference държи референция, която не предотвратява унищожаването на обекта — полезно за кешове без течове.
Изключения от __toString()
Хвърлянето от __toString() е позволено (преди — fatal). Част от старите recoverable fatals са станали Error — одитирайте string casting.
Сериализация: __serialize / __unserialize
Нов механизъм, който постепенно измества Serializable:
final class Point
{
public function __serialize(): array
{
return ['x' => $this->x, 'y' => $this->y];
}
public function __unserialize(array $data): void
{
$this->x = $data['x'];
$this->y = $data['y'];
}
}
SPL типове като ArrayObject могат да създават нови сериализирани натоварвания, четими на 7.4+, но не на по-стари PHP.
Разширения и стандартна библиотека
- FFI: извикване на C библиотеки (мощно; изисква сигурност).
- OPcache preloading:
opcache.preload, честоopcache.preload_user. mb_str_split(): катоstr_split(), но по кодпойнти.proc_open(): команда като масив (без shell), дескрипториredirect/null.strip_tags(): позволени тагове като масив от имена.- PDO: user/pass в DSN за повече драйвери;
??в SQL екранира литерален?(напр. при PostgreSQL JSON оператори). - PCRE:
preg_replace_callback*приемаflags—PREG_OFFSET_CAPTURE,PREG_UNMATCHED_AS_NULLи др. - Password: Argon2 през sodium без libargon.
Практични рецепти
Подразбирания с ??=
$options['timeout'] ??= 30;
Arrow function в сортиране
usort($rows, fn($a, $b) => $a['score'] <=> $b['score']);
Spread-merge на динамични списъци
$merged = array_merge(...$chunks);
Обратно несъвместими промени (миграционни бележки)
Ядро
- Достъп като масив към не-масиви:
$null["key"]и подобни заnull,bool,int,float,resource— notice. get_declared_classes(): вече не връща анонимни класове, докато не са инстанцирани.fn: запазена ключова дума за имена на функции/класове.<?phpв края на файл без нов ред: вече се тълкува като отварящ PHP таг (преди зависеше отshort_open_tag).- Stream wrappers: при
include/requireна stream може да се извикаstreamWrapper::stream_set_option(STREAM_OPTION_READ_BUFFER)— имплементирайте метода или върнетеfalse, за да няма warning. - Сериализация: формат
oе премахнат (актуално само за ръчно съставени низове). - Константи за password алгоритми:
PASSWORD_*са низове ('2y','argon2id', …), не цели — код, сравняващ с1/2/3, се чупи. htmlentities(): notice, когато кодирането се свежда до поведение катоhtmlspecialchars.fread/fwrite: при неуспех връщатfalse(не''/0); възможен е notice.- BCMath: предупреждение при лошо формирани числови низове (като преди се интерпретира като нула).
- CURL: сериализация на
CURLFileхвърля по-рано; нестандартен аргумент наcurl_version()— предупреждение/игнориране. - Date:
var_dumpнаDateTime*не оставя „излишни“ свойства; сравнение наDateIntervalпредупреждава и винаги еfalse. - Intl: по подразбиране
idn_to_ascii/idn_to_utf8използватINTL_IDNA_VARIANT_UTS46. - MySQLi: премахнат embedded server; премахнато недокументираното
$mysqli->stat— ползвайтеmysqli::stat(). - OpenSSL:
openssl_random_pseudo_bytesхвърля катоrandom_bytesпри грешка;$crypto_strongеtrue, ако няма изключение. - PCRE: с
PREG_UNMATCHED_AS_NULLопашните несъвпаднали групи саnull(стабилен размер на$matches). - PDO: сериализация на
PDO/PDOStatementхвърляException(неPDOException). - Reflection: сериализация на reflection обекти хвърля; променени са числови стойности на някои константи за модификатори.
- SPL /
ArrayObject: променено поведение наget_object_varsбезSTD_PROP_LIST;SplPriorityQueue::setExtractFlags(0)хвърля веднага. - Tokenizer: неочаквани байтове стават
T_BAD_CHARACTERвместо „празнини“ в потока. - Бисквитки (от 7.4.11): имената на входящи cookies не се URL-декодират.
Deprecated (поправете рано)
Акценти:
- Вложени тернарни оператори без явни скоби (освен еднозначната форма с влагане в средния операнд).
- Фигурни скоби за offset
$str{0}/$arr{0}→ използвайте[]. (real)иis_real()→(float)/is_float().array_key_exists()върху обекти →isset()/property_exists().implode($parts, $glue)— обърнат ред →implode($glue, $parts).ReflectionType::__toString()иReflection*::export()→ API катоReflectionNamedType::getName()и string cast на reflection обекти.allow_url_include,FILTER_SANITIZE_MAGIC_QUOTES, остарели LDAP paged функции,money_format(),hebrevc()и др. — пълен списък: migration74 deprecated.
Други промени и експлоатация
zend.exception_ignore_args: нов INI (по подразбиране може да скрие аргументи в stack traces — проверете error reporting).opcache.preload_user: потребител за preload, когато не е root.- Миграция към pkg-config: много
./configureфлагове вече не приемат=DIR; ползвайтеPKG_CONFIG_PATHилиFOO_CFLAGS/FOO_LIBS. - Премахнати бандли: SQLite3, Zip, onig (mbregex) — нужни са системни библиотеки; hash винаги е включен.
- CSV: празен низ за
$escapeизключва PHP escape механизма;str_getcsv()е съгласуван. - GD:
imagecropauto()синхронизиран със system libgd; променен default режим;imagescale()с-1за запазване на пропорции. - PEAR: не се инсталира по подразбиране (
--with-pearопционално и deprecated). - Производителност: opcode за
array_key_exists()при статично разрешаване; UTF-8preg_matchвалидира низа веднъж при повторни извиквания.
Обобщение
PHP 7.4 е мост към 8.x: въведете typed properties и __serialize/__unserialize рано; търсете fn, $var{idx}, целочислени password алгоритми и чуплив ArrayObject код; тествайте streams, OpenSSL random и сериализация на PDO/Reflection.