While not as exciting as previous release, PHP 8.2 brings some nice addition to the language. Let's have a look at them:
true, false, null are standalone type now
While, we could use null and false with with other types as union type, from now on they can be used separately as well.
example:
#On PHP 8.1
// union type, allowed
function bazz(): array|null
{
return null;
}
// union type, allowed
function bazz(): string|false
{
return false;
}
// null as standalone type, not allowed
function bazz(): null
{
return null;
}
// false as standalone type, not allowed
function bazz(): false
{
return false;
}
Two of the above function will trigger a error "Fatal error: Null/False can not be used as a standalone type". But with PHP 8.2, they works fine, including true:
#On PHP 8.2
function bazz(): null
{
return null;
}
function bazz(): false
{
return false;
}
function bazz(): true
{
return true;
}
But why do they have been added?
Note: true|false union type is not allowed. bool type is recommended for such use-case.
New execute_query function for mysql
To avoid SQL injection, prepared statement is always recommended for mysql query. But code for preparing SQL statements is quite verbose. We need to call three different function to execute a query and fetch the result.
<?php
$statment = $mysql->prepare("SELECT * FROM users WHERE id = ?");
$statement->execute([$id]);
foreach($statement->get_result() as $row) {
var_dump($row);
}
But, with PHP 8.2 we can now reduce all these three function call to a single execute_query() call:
foreach($mysql->execute_query("SELECT * FROM users WHERE id = ?", [$id]) as $row) {
var_dump($row);
}
Isn't that sweet? :)
readonly classes
On PHP 8.1, we got this awesome feature to flag class properties as "readonly" so they can be written only once in the construct. People like me really liked this feature, and used a lot in our codebase, specially for DTOs. But When we want all properties of DTOs to be readonly, it's kinda boring and pain to define each properties as readonly.
Fear not, PHP 8.2 now allows us to define whole class as "readonly". readonly classes automatically marks all of its properties as readonly. Also, dynamic properties are not allowed.
readonly class Foo
{
public int $bar;
public function __construct() {
$this->bar = 1;
}
}
$foo = new Foo();
$foo->bar = 2;
// Fatal Error: Uncaught Error: Cannot modify readonly property Foo::$bar
$foo->baz = 1;
// Fatal Error: Uncaught Error: Cannot create dynamic property Foo::$baz
Note:
dynamic class properties are now deprecated
Uhh, dynamic class properties, what a feature. I wasted so many hours of my life because of this feature. While I abused this feature a lot too, but the fact that a single typo can cause debug nightmare is unacceptable to me. I'm sure you've faced such situation too:
class User
{
public $name;
public function __construct(string $name){
$this->name = $name;
}
}
$user = new User('John');
// some code
$user->nane = 'Doe'; // notice anything?
// some other code
echo $user->name;
// umm, why it prints John?
I know, modern IDE helps to prevent such scenario but there are lot of cases where dynamic properties bring more risks that the benefits.
PHP 8.2 prevent this behavior. Accessing a non-existent property on a object no longer silently creates the property. Instead it throws "Deprecated: Creation of dynamic property User::$nane is deprecated" error.
BTW, if your code uses __get/__set magic method to achieve similar effect, then you don't have to worry, these methods are not affected by this change.
But, I still need dynamic properties in my codebase
In that case you have two option:
deprecated utf8_encode and utf8_decode
Due to some limitations specified in the RFC, using utf8_encode and utf8_decode functions will throw deprecation warning. Also, they will be removed on PHP 9.
Instead, mb_convert_encoding
is recommended.
iterator function now accept arrays
functions such as iterator_to_array() and iterator_count() currently only accepts iterator as input. PHP 8.2 makes it easier by allowing us to pass regular arrays to them as well.
Hiding parameters in back traces
PHP exception stack traces are awesome. They really help a lot during debugging an error. For each trace, they contains original parameters so we can inspect it and find potential bug. But it has a drawback. Sometimes we pass sensitive information (such as password or secret keys) to functions are parameter. And these information gets written to log whenever a exception happens. Sensitive information should not be exposed like that.
To overcome this drawback, PHP 8.2 introduces new attribute called #[\SensitiveParameter]
With this, we simply add this attribute to any parameter that we think is sensitive, and inside trace log, they will be replaced by SensitiveParameterValue object.
// we don't want $password to be in stack trace
function db_connect
(
string $host,
#[\SensitiveParameter]
string $password
)
{
throw new Exception("DB connection failed");
}
db_connect('localhost', 'password');
/*
Fatal error: Uncaught Exception: DB connection failed in file.php:9
Stack trace:
#0 file.php(12): db_connect('localhost', Object(SensitiveParameterValue))
#1 {main}
thrown in file.php on line 9
*/
New random extension
A new extension named random has been introduced. It provides a OOP interface to generate random integers. Due to its design, it is much easier to mock for testing purpose.
Constants in traits
Although I don't like this, but PHP 8.2 now supports declaring constants in traits.
trait Bar
{
const SOMETHING = 1;
}
class Foo
{
use Bar;
}
echo Foo::SOMETHING; //allowed
echo Bar::SOMETHING; // direct access via trait is not allowed
ini_parse_quantity function
In php.ini, there are some values that represents byte data size in various unit, such as 512K, 64M, 1G
ini_parse_quantity() function can parse these values and return bytes in integer.
ini_parse_quantity('64K'); // 65536
curl_upkeep function
Curl extension has brought us a new function to keep a curl connection alive. curl_upkeep() does this by sending small amount of traffic to the existing connection. Currently it only supports HTTP/2 connections.
imap_is_open
This new function imap_is_open() checks if a imap connection is still open or not. It accepts IMAP\Connection object and return bool.
str_split now return empty array on empty string
Before 8.2, str_split() used to return array of a single empty string if an empty string was provided as input. PHP 8.2 changes this behavior, it now return empty array
// php 8.1
str_split(""); // returns [""]
//php 8.2
str_split(""); // returns []
memory_reset_peak_usage
If you need to reset memory usage data returned by memory_get_peak_usage(). memory_reset_peak_usage() can do that.
openssl_cipher_key_length
This new openssl_cipher_key_length() function returns key length of the provided cipher algo:
openssl_cipher_key_length('AES-128-CBC'); // 16
Which of these features did you like the most? Let me know by commenting bellow.
Write comment about this article: