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_BR
class 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->countryCode, $this->languageCode] = 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_BR
class 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]
Attribute RFC
Doc
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]
attribute makes PHP’s existing deprecation mechanism available to user-defined functions, methods, and class constants. $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)
New DOM API that includes standards-compliant support for parsing HTML5 documents, fixes several long-standing compliance bugs in the behavior of the DOM functionality, and adds several functions to make working with documents more convenient.
The new DOM API is available within the Dom
namespace. Documents using the new DOM API can be created using the Dom\HTMLDocument
and Dom\XMLDocument
classes.
$num1 = '0.12345';
$num2 = 2;
$result = bcadd($num1, $num2, 5);
echo $result; // '2.12345'
var_dump(bccomp($num1, $num2) > 0); // false
use BCMath\Number;
$num1 = new Number('0.12345');
$num2 = new Number('2');
$result = $num1 + $num2;
echo $result; // '2.12345'
var_dump($num1 > $num2); // false
BCMath allows you to work with arbitrary precision float numbers in PHP. With this release, you can benefit from object-oriented style and operator overloading to use BCMath numbers.
It means, you can now use standard operators with BcMath\Number
objects, which also support all bc*
functions.
These objects are immutable and implement the Stringable
interface, so they can be used in string contexts like echo $num
.
array_*()
functions 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
, and Pdo\Sqlite
of PDO
are available. new MyClass()->method()
without parentheses RFC
Doc
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
expression in parenthesis. request_parse_body()
function.bcceil()
, bcdivmod()
, bcfloor()
, and bcround()
functions.RoundingMode
enum for round()
with 4 new rounding modes TowardsZero
, AwayFromZero
, NegativeInfinity
, and PositiveInfinity
.DateTime::createFromTimestamp()
, DateTime::getMicrosecond()
, DateTime::setMicrosecond()
, DateTimeImmutable::createFromTimestamp()
, DateTimeImmutable::getMicrosecond()
, and DateTimeImmutable::setMicrosecond()
methods.mb_trim()
, mb_ltrim()
, mb_rtrim()
, mb_ucfirst()
, and mb_lcfirst()
functions.pcntl_getcpu()
, pcntl_getcpuaffinity()
, pcntl_getqos_class()
, pcntl_setns()
, and pcntl_waitid()
functions.ReflectionClassConstant::isDeprecated()
, ReflectionGenerator::isClosed()
, and ReflectionProperty::isDynamic()
methods.http_get_last_response_headers()
, http_clear_last_response_headers()
, and fpow()
functions.XMLReader::fromStream()
, XMLReader::fromUri()
, XMLReader::fromString()
, XMLWriter::toStream()
, XMLWriter::toUri()
, and XMLWriter::toMemory()
methods.grapheme_str_split()
function._
as a class name is now deprecated.round()
throws ValueError
.date
, intl
, pdo
, reflection
, spl
, sqlite
, xmlreader
are typed now.GMP
class is now final.MYSQLI_SET_CHARSET_DIR
, MYSQLI_STMT_ATTR_PREFETCH_ROWS
, MYSQLI_CURSOR_TYPE_FOR_UPDATE
, MYSQLI_CURSOR_TYPE_SCROLLABLE
, and MYSQLI_TYPE_INTERVAL
constants have been removed.mysqli_ping()
, mysqli_kill()
, mysqli_refresh()
functions, mysqli::ping()
, mysqli::kill()
, mysqli::refresh()
methods, and MYSQLI_REFRESH_*
constants have been deprecated.stream_bucket_make_writeable()
and stream_bucket_new()
now return an instance of StreamBucket
instead of stdClass
.exit()
behavioral change.E_STRICT
constant has been deprecated.