Tim Bond
MergePHP - November 14, 2024
| Date | Milestone |
|---|---|
| Jul 04 2024 | Alpha 1 |
| Jul 18 2024 | Alpha 2 |
|
|
|
| Aug 01 2024 | Alpha 4 |
| Aug 13 2024 | Feature freeze |
|
|
|
|
|
|
| Aug 15 2024 | Beta 3 |
| Aug 29 2024 | Beta 4 |
| Sep 12 2024 | Beta 5 |
| Sep 26 2024 | RC 1 |
| Oct 10 2024 | RC 2 |
| Oct 24 2024 | RC 3 |
| Nov 07 2024 | RC 4 👈 |
| Nov 21 2024 | GA |
new MyClass()->method() without parentheses
// < 8.4
echo (new DateTimeImmutable())->getTimestamp();
// 8.4
echo new DateTimeImmutable()->getTimestamp();
https://wiki.php.net/rfc/new_without_parentheses
New array_*()Â functions
$animal = array_find(
['dog', 'cat', 'cow', 'duck', 'goose'],
static function (string $value) {
return str_starts_with($value, 'c');
}
);
var_dump($animal); // string(3) "array_find"https://wiki.php.net/rfc/array_find
-
array_find
- Returns the first element satisfying a callback function
-
array_find_key
- Returns the key of the first element satisfying a callback function
-
array_any
- Checks if at least one array element satisfies a callback function
-
array_all
- Checks if all array elements satisfy a callback function
New array_*()Â functions
Asymmetric Visibility
class PhpVersion
{
public private(set) string $version = '8.4';
}
$phpVersion = new PhpVersion();
var_dump($phpVersion->version); // string(3) "8.4"
$phpVersion->version = 'PHP 8.3'; // Visibility errorhttps://wiki.php.net/rfc/asymmetric-visibility-v2
class PhpVersion
{
public string $version = '8.3';
}
$phpVersion = new PhpVersion();
var_dump($phpVersion->version); // string(3) "8.3"
$phpVersion->version = 'PHP 8.4'; // No errorDeprecated Attribute
/**
* @deprecated 8.3 use get_bar() instead
*/
function get_foo() {
return 'foo';
}
$value = get_foo();
// No indication that the method is deprecatedhttps://wiki.php.net/rfc/deprecated_attribute
#[\Deprecated(
message: "use get_bar() instead",
since: "8.4"
)]
function get_foo() {
return 'foo';
}
$value = get_foo();
// Deprecated: Method get_foo() is deprecated
// since 8.4, use get_bar() insteadProperty Hooks
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_BRhttps://wiki.php.net/rfc/property-hooks
$brazilianPortuguese = new Locale('pt', 'br');
var_dump($brazilianPortuguese->countryCode); // BR
var_dump($brazilianPortuguese->combinedCode); // pt_BRDeprecated Implicit nullable types
function save(Book $book = null) {}
// Deprecated: Implicitly marking parameter $book as
// nullable is deprecated, the explicit nullable type
// must be used instead
function save(?Book $book = null) {}https://wiki.php.net/rfc/deprecate-implicitly-nullable-types
PDO Driver specific SQL parsers
<?php
$connection = new PDO(
'mysql:host=localhost;dbname=test',
$username,
$password,
);
// in 8.4: object(Pdo\Mysql)
// previously: object(PDO)
$connection->sqliteCreateFunction(
'append_php',
static fn($string) => 'PHP ' . $string
); // Fatalhttps://wiki.php.net/rfc/pdo_driver_specific_parsers
Lazy Objects
<?php
$initializer = static function (MyClass $proxy): MyClass {
return new MyClass(123);
};
$reflector = new ReflectionClass(MyClass::class);
$object = $reflector->newLazyProxy($initializer);https://wiki.php.net/rfc/lazy-objects
Deprecated: _ as a class name
class _ {
}exit() behavioral change
https://wiki.php.net/rfc/exit-as-function
- The
exit()(anddie()) language constructs now behave more like a function - Can now be passed like callables
- Are affected by the strict_types declare statement
- Perform the type coercions (instead of casting any non-integer value to a string)
- Passing invalid types (not int or string) to now result in a TypeError
New bcmath functions
https://wiki.php.net/rfc/adding_bcround_bcfloor_bcceil_to_bcmath
bcceil()bcdivmod()bcfloor()bcround()
New mb_ functions
https://wiki.php.net/rfc/mb_trim
-
mb_trim()
-
mb_ltrim()
-
mb_rtrim()
-
mb_ucfirst()
-
mb_lcfirst()
New XML functions
- Â XMLReader::fromStream()
- XMLReader::fromUri()
- XMLReader::fromString()
- XMLWriter::toStream()
- XMLWriter::toUri()
- XMLWriter::toMemory()
New header functions
- http_get_last_response_headers()
- http_clear_last_response_headers()
New request_parse_body() function
// On a a PUT request
var_dump($_POST); // []
var_dump($_FILES); // []https://wiki.php.net/rfc/rfc1867-non-post
function request_parse_body(?array $options = null): array {}
// usage:
[$_POST, $_FILES] = request_parse_body();
// options:
// max_file_uploads
// max_input_vars
// max_multipart_body_parts
// post_max_size
// upload_max_filesize
PHP 8.4 security support until 31 Dec 2028
Release Cycle Update
https://wiki.php.net/rfc/release_cycle_update
- Allow features that do not require an RFC in the beta period
- Disallow new features in release candidates and bug fix releases
- Reduce number of RCs to four (was six)
- Extend security support by one year
- Allowing recent regression fixes during security support
How can I play with it now?
- Easy:
docker container run --rm php:8.4.0RC3-cli php -i - Medium:
- POSIX
docker container run --rm -v $(pwd):/app/ php:8.4.0RC3-cli php /app/script.php
-
Windows - cmd
docker container run --rm -v %cd%:/app/ php:8.4.0RC3-cli php /app/script.php
-
Windows - PowerShell
docker container run --rm -v ${PWD}:/app/ php:8.4.0RC3-cli php /app/script.php
- POSIX
- Hard:
FROM php:8.4.0RC3-...
What's New in PHP 8.4
By Tim Bond
What's New in PHP 8.4
MergePHP - November 9, 2023
- 113