class Locale
{
    private string $languageCode;
    private string $countryCode;
    public function __construct(string $languageCode, string $countryCode)
    {
        $this->setLanguageCode($languageCode);
        $this->setCountryCode($countryCode);
    }
    public function getLanguageCode(): string
    {
        return $this->languageCode;
    }
    public function setLanguageCode(string $languageCode): void
    {
        $this->languageCode = $languageCode;
    }
    public function getCountryCode(): string
    {
        return $this->countryCode;
    }
    public function setCountryCode(string $countryCode): void
    {
        $this->countryCode = strtoupper($countryCode);
    }
    public function setCombinedCode(string $combinedCode): void
    {
        [$languageCode, $countryCode] = explode('_', $combinedCode, 2);
        $this->setLanguageCode($languageCode);
        $this->setCountryCode($countryCode);
    }
    public function getCombinedCode(): string
    {
        return \sprintf("%s_%s", $this->languageCode, $this->countryCode);
    }
}
$brazilianPortuguese = new Locale('pt', 'br');
var_dump($brazilianPortuguese->getCountryCode()); // BR
var_dump($brazilianPortuguese->getCombinedCode()); // pt_BRclass Locale
{
    public string $languageCode;
    public string $countryCode
    {
        set (string $countryCode) {
            $this->countryCode = strtoupper($countryCode);
        }
    }
    public string $combinedCode
    {
        get => \sprintf("%s_%s", $this->languageCode, $this->countryCode);
        set (string $value) {
            [$this->languageCode, $this->countryCode] = explode('_', $value, 2);
        }
    }
    public function __construct(string $languageCode, string $countryCode)
    {
        $this->languageCode = $languageCode;
        $this->countryCode = $countryCode;
    }
}
$brazilianPortuguese = new Locale('pt', 'br');
var_dump($brazilianPortuguese->countryCode); // BR
var_dump($brazilianPortuguese->combinedCode); // pt_BRclass PhpVersion
{
    private string $version = '8.3';
    public function getVersion(): string
    {
        return $this->version;
    }
    public function increment(): void
    {
        [$major, $minor] = explode('.', $this->version);
        $minor++;
        $this->version = "{$major}.{$minor}";
    }
}class PhpVersion
{
    public private(set) string $version = '8.4';
    public function increment(): void
    {
        [$major, $minor] = explode('.', $this->version);
        $minor++;
        $this->version = "{$major}.{$minor}";
    }
}#[\Deprecated]                RFC
                Документация
            class PhpVersion
{
    /**
     * @deprecated 8.3 use PhpVersion::getVersion() instead
     */
    public function getPhpVersion(): string
    {
        return $this->getVersion();
    }
    public function getVersion(): string
    {
        return '8.3';
    }
}
$phpVersion = new PhpVersion();
// No indication that the method is deprecated.
echo $phpVersion->getPhpVersion();class PhpVersion
{
    #[\Deprecated(
        message: "use PhpVersion::getVersion() instead",
        since: "8.4",
    )]
    public function getPhpVersion(): string
    {
        return $this->getVersion();
    }
    public function getVersion(): string
    {
        return '8.4';
    }
}
$phpVersion = new PhpVersion();
// Deprecated: Method PhpVersion::getPhpVersion() is deprecated since 8.4, use PhpVersion::getVersion() instead
echo $phpVersion->getPhpVersion();#[\Deprecated] расширяет существующий механизм объявления сущности устаревшей для пользовательских функций, методов и констант классов.            $dom = new DOMDocument();
$dom->loadHTML(
    <<<'HTML'
        <main>
            <article>PHP 8.4 is a feature-rich release!</article>
            <article class="featured">PHP 8.4 adds new DOM classes that are spec-compliant, keeping the old ones for compatibility.</article>
        </main>
        HTML,
    LIBXML_NOERROR,
);
$xpath = new DOMXPath($dom);
$node = $xpath->query(".//main/article[not(following-sibling::*)]")[0];
$classes = explode(" ", $node->className); // Simplified
var_dump(in_array("featured", $classes)); // bool(true)$dom = Dom\HTMLDocument::createFromString(
    <<<'HTML'
        <main>
            <article>PHP 8.4 is a feature-rich release!</article>
            <article class="featured">PHP 8.4 adds new DOM classes that are spec-compliant, keeping the old ones for compatibility.</article>
        </main>
        HTML,
    LIBXML_NOERROR,
);
$node = $dom->querySelector('main > article:last-child');
var_dump($node->classList->contains("featured")); // bool(true)Новый DOM API, который поддерживает разбор HTML5-документов в соответствии со стандартами, исправляет несколько давних ошибок в поведении DOM и добавляет несколько функций, делающих работу с документами более удобной.
Новый DOM API доступен в пространстве имён Dom. Документы, использующие новый DOM API, могут быть созданы с помощью классов Dom\HTMLDocument и Dom\XMLDocument.
$num1 = '0.12345';
$num2 = '2';
$result = bcadd($num1, $num2, 5);
echo $result; // '2.12345'
var_dump(bccomp($num1, $num2) > 0); // falseuse BcMath\Number;
$num1 = new Number('0.12345');
$num2 = new Number('2');
$result = $num1 + $num2;
echo $result; // '2.12345'
var_dump($num1 > $num2); // falseНовый объект BcMath\Number позволяет использовать объектно-ориентированный стиль и стандартные математические операторы при работе с числами произвольной точности.
Эти объекты неизменяемы и реализуют интерфейс Stringable, поэтому их можно использовать в строковых контекстах, например, echo $num.
array_*()                RFC
            $animal = null;
foreach (['dog', 'cat', 'cow', 'duck', 'goose'] as $value) {
    if (str_starts_with($value, 'c')) {
        $animal = $value;
        break;
    }
}
var_dump($animal); // string(3) "cat"$animal = array_find(
    ['dog', 'cat', 'cow', 'duck', 'goose'],
    static fn(string $value): bool => str_starts_with($value, 'c'),
);
var_dump($animal); // string(3) "cat"$connection = new PDO(
    'sqlite:foo.db',
    $username,
    $password,
); // object(PDO)
$connection->sqliteCreateFunction(
    'prepend_php',
    static fn($string) => "PHP {$string}",
);
$connection->query('SELECT prepend_php(version) FROM php');$connection = PDO::connect(
    'sqlite:foo.db',
    $username,
    $password,
); // object(Pdo\Sqlite)
$connection->createFunction(
    'prepend_php',
    static fn($string) => "PHP {$string}",
); // Does not exist on a mismatching driver.
$connection->query('SELECT prepend_php(version) FROM php');Pdo\Dblib, Pdo\Firebird, Pdo\MySql, Pdo\Odbc, Pdo\Pgsql, Pdo\Sqlite драйверов, наследующие PDO.            new MyClass()->method() без скобок                RFC
                Документация
            class PhpVersion
{
    public function getVersion(): string
    {
        return 'PHP 8.3';
    }
}
var_dump((new PhpVersion())->getVersion());class PhpVersion
{
    public function getVersion(): string
    {
        return 'PHP 8.4';
    }
}
var_dump(new PhpVersion()->getVersion());new в круглые скобки.            request_parse_body().bcceil(), bcdivmod(), bcfloor() и bcround().RoundingMode для функции round() с 4 режимами: TowardsZero, AwayFromZero, NegativeInfinity и PositiveInfinity.DateTime::createFromTimestamp(), DateTime::getMicrosecond(), DateTime::setMicrosecond(), DateTimeImmutable::createFromTimestamp(), DateTimeImmutable::getMicrosecond() и DateTimeImmutable::setMicrosecond().mb_trim(), mb_ltrim(), mb_rtrim(), mb_ucfirst() и mb_lcfirst().pcntl_getcpu(), pcntl_getcpuaffinity(), pcntl_getqos_class(), pcntl_setns() и pcntl_waitid().ReflectionClassConstant::isDeprecated(), ReflectionGenerator::isClosed() и ReflectionProperty::isDynamic().http_get_last_response_headers(), http_clear_last_response_headers(), fpow().XMLReader::fromStream(), XMLReader::fromUri(), XMLReader::fromString(), XMLWriter::toStream(), XMLWriter::toUri() и XMLWriter::toMemory().grapheme_str_split().null объявлены устаревшими._ в качестве имени класса объявлено устаревшим.round() выбрасывает ошибку ValueError.date, intl, pdo, reflection, spl, sqlite и xmlreader типизированы.GMP теперь является окончательным.MYSQLI_SET_CHARSET_DIR, MYSQLI_STMT_ATTR_PREFETCH_ROWS, MYSQLI_CURSOR_TYPE_FOR_UPDATE, MYSQLI_CURSOR_TYPE_SCROLLABLE и MYSQLI_TYPE_INTERVAL.mysqli_ping(), mysqli_kill(), mysqli_refresh(), методы mysqli::ping(), mysqli::kill(), mysqli::refresh() и константы MYSQLI_REFRESH_* объявлены устаревшими.stream_bucket_make_writeable() и stream_bucket_new() теперь возвращают экземпляр класса StreamBucket вместо stdClass.exit().E_STRICT объявлена устаревшей.