If you were one of the people and developers who were waiting for PHP 8.2 to roll out, we’ve good news for you!
PHP 8.2 was released on the 8th of December 2022 to minimize the limitations of the previous versions while making the life of developers easy and smooth. Most PHP 8.2 changes are there to simplify the coding process while deprecating some of the unuseful or trouble-making older functions. Upgrading to a new PHP 8.2 will help you maximize the site’s security while getting used to the new syntax.
The new PHP 8.2 is a major update of the language containing various features, including readonly classes, null, false, and true as stand-alone types, deprecated dynamic properties, performance improvements, and more.
Here in this blog, we’ve discussed all the new changes and features of PHP 8.2 for you to decide if it’s worth upgrading and switching.
New Features & Improvements of PHP 8.2:
Readonly Classes:
First introduced in PHP 8.1, readonly used to feature class properties, but now with PHP 8.2, you can declare an entire class as readonly. When you declare the whole class as readonly with PHP 8.2, all the properties will automatically inherit the readonly feature, the same as declaring every class property as readonly.
Let’s say, if in PHP 8.1, to make readonly classes, you had to write:
class MyClass
{ public readonly string $myValue, public readonly int $myOtherValue public readonly string $myAnotherValue public readonly int $myYetAnotherValue } |
But with PHP 8.2, you can make readonly classes only with much ease.
PHP 8.2 code for readonly:
Moreover, you can also declare abstract or final classes as readonly regardless of the keyword orders.
For Example,
abstract readonly class Free {} |
OR
final readonly class Dom {} |
Additionally, you can also declare a readonly class with no properties, but that will prevent dynamic properties while still allowing child classes to declare their readonly properties exclusively.
Furthermore, same as individual readonly properties, readonly classes can contain typed properties only. However, you can type mixed-type property if you are unable to declare a strictly typed property.
If you declare a readonly class without a typed property will result in a fatal error with a message like:
readonly class Type { public $nope;
} |
Fatal error: Readonly property Type::$nope must have type in … on line … |
Plus, you need to note that you cannot declare readonly for some particular PHP features like Enums (as they cannot contain any property), traits, and interfaces.
If you try to do so anyway, it will result in a Parse error like
readonly interface Destiny {}Parse error: syntax error, unexpected token “interface”, expecting “abstract” or “final” or “readonly” or “class” in … on line … |
As PHP 8.2 deprecates dynamic properties, you cannot prevent them from being added to a class. If you do so, it will result in a fatal error with a message like:
Fatal error: Readonly property Test::$test must have type in … on line … |
Allowance of true, false, and null as Standard Types:
Though PHP already includes scalar types like int, string, and bool in the expanded version of PHP 8.0 along with additional union types, they weren’t allowed as standalone types. The same was the case with RFC, as they allowed using false and null as part of union types but not as standalone types.
If you had tried declaring false or null or as standalone types without making them a part of a union type, it used to result in a fatal error.
For example,
function spam(): null {}
function eggs(): false {} Fatal error: Null can not be used as a standalone type in … on line … Fatal error: False can not be used as a standalone type in … on line … |
But now, with PHP 8.2, you can use them as standalone and declare the return, parameter, and property types precisely, making the PHP system more advanced and complete.
Earlier, PHP didn’t have a true type and seemed to act as a natural counterpart of the false type. Nonetheless, PHP 8.2 has fixed that by adding support for all the true types, which behave the same as how false type behaves.
However, to avoid redundancy, you can’t declare true, false, and null in a union type, as it results in a compile-time fatal error.
Disjunctive Normal Form: Combined Unions and Intersections
In PHP, Disjunctive Normal Form (DNF) is an effective and organized way of organizing boolean expressions like OR and AND. Using DNF makes it possible for the parser to handle Union and Intersection types.
With PHP 8.2, you can have a simple and effective DNF feature.
Here’s the example of RFC with an assumption that the required interface and class are already in existence:
For Example,
interface A {}
interface B {} interface C extends A {} interface D {} class W implements A {} class X implements B {} class Y implements A, B {} class Z extends Y implements C {} |
Moreover, with PHP 8.2, you can also perform type declaration for properties, parameters, and return values.
Here’s an example of that,
// Accepts an object that implements both A and B,
// OR an object that implements D (A&B)|D // Accepts an object that implements C, // OR a child of X that also implements D, // OR null C|(X&D)|null // Accepts an object that implements all three of A, B, and D, // OR an int, // OR null. (A&B&D)|int|null |
If the properties are not in the DNF forms, declaring them as such will lead to a parse error. To solve the issue, you need to rewrite them in DNF format.
For example,
You can write (A&B)|(A&D) instead of A&(B|D) or A|(B&D)|(B&W)|null instead of A|(B&(D|W)|null). |
Additionally, you need to ensure that each DNF-type segment is unique.
For example,
(A&B)|(B&A) is an invalid request as both the alternative represents the same segments and returns to the same logic.
Furthermore, you can’t use the strict subset of the superset, as the superset will already have all instances.
New Random Extension RFC
Source: php.net
One of the PHP 8.2 changes includes a new random extension acting as a better substitute than the previous one. New PHP 8.2 is a random number generator that is easier to maintain, more performant, more secure, and doesn’t rely on a global state, making detecting bugs easier.
Randomizer is a new class in PHP 8.2 that accepts a randomizer engine, and you can change that engine depending on your preference and requirements.
Here’s an example of a new “Random” extension:
use Random\Engine\Xoshiro256StarStar;
use Random\Randomizer; $blueprintRng = new Xoshiro256StarStar( hash(‘sha256’, “Example seed that is converted to a 256 Bit string via SHA-256”, true) ); $fibers = []; for ($i = 0; $i < 8; $i++) { $fiberRng = clone $blueprintRng; // Xoshiro256**’s ‘jump()’ method moves the blueprint ahead 2**128 steps, as if calling // ‘generate()’ 2**128 times, giving the Fiber 2**128 unique values without needing to reseed. $blueprintRng->jump(); $fibers[] = new Fiber(function () use ($fiberRng, $i): void { $randomizer = new Randomizer($fiberRng); echo “{$i}: ” . $randomizer->getInt(0, 100), PHP_EOL; }); } // The randomizer will use a CSPRNG by default. $randomizer = new Randomizer(); // Even though the fibers execute in a random order, they will print the same value // each time because each has its own unique instance of the RNG. $fibers = $randomizer->shuffleArray($fibers); foreach ($fibers as $fiber) { $fiber->start(); } |
Allow Constants in Traits
In PHP, Traits are a way to reuse code, and they are great for accessibility across classes. With PHP 8.2, you can now define constants in its composing class or an interface implemented by its composing class.
Here’s an example straight from the RFC:
trait Foo {
public const FLAG_1 = 1; protected const FLAG_2 = 2; private const FLAG_3 = 2; public function doFoo(int $flags): void { if ($flags & self::FLAG_1) { echo ‘Got flag 1’; } if ($flags & self::FLAG_2) { echo ‘Got flag 2’; } if ($flags & self::FLAG_3) { echo ‘Got flag 3’; } } } |
Moreover, Trait constants are merged into the composing class’ definition same as its property and method definitions. Trait constants have similar restrictions as Trait properties. Nonetheless, there is a scope for improvement to flesh out the feature.
AllowDynamicProperties Attribute
Another great 8.2 change includes deprecating dynamic variables in classes resulting in a deprecation message in PHP 8.2 and an ErrorException in future versions of PHP. To solve this error, a new #[AllowDynamicProperties] attribute will be added to allow dynamic properties for classes.
Here’s an example of RFC:
class Foo {}
$foo = new Foo; // Deprecated: Creation of dynamic property Foo::$bar is deprecated $foo->bar = 1; // No deprecation warning: Dynamic property already exists. $foo->bar = 2; |
Deprecated Features in PHP 8.2
There are many deprecated features rolled out in PHP 8.2 update. Here’s the list of all the deprecated features in detail.
#utf8_encode() and utf8_decode() Functions
The use of utf8_encode() and utf8_decode()functions was to convert between ISO-8859-1 and UTF-8 encoding standards. However, because of its limitations, like lack of error messages, warnings, and limited encoding support, PHP 8.2 have deprecated these functions. You can use iconv or intl extensions to convert the encoding standard.
Mbstring: Base64, Uuencode, QPrint, and HTML Entity Encodings
The next on the list is Mbstring. It is used for converting several character encoding standards like UTF-8/16/32 and ISO-8859-1. Mbstring includes support for Base64, Quoted-Printable, Uuencode, and HTML Entities.
The problem relies upon the formats as they process information in raw bytes instead of sequences of bytes. As there are already separate functions in PHP for encoding and decoding, PHP 8.2 has deprecated the mbstring extension with the following labeled encodings:
BASE64
UUENCODE
HTML-ENTITIES
HTML (alias of HTML-ENTITIES)
Quoted-Printable
qprint (alias of Quoted-Printable)
Partially-Supported Callables
Last but not least, PHP 8.2 has deprecated partially-supported callables that are not compatible with the $callable() pattern. Here’s the list of deprecated callables:
$callable = “self::method”;
$callable = “parent::method”; $callable = “static::method”; $callable = [“self,” “method”]; $callable = [“parent,” “method”]; $callable = [“static,” “method”]; $callable = [“MyClass”, “MyParentClass::myMethod”]; $callable = [new MyClass(), “MyOtherClass::myMethod”]; |
To avoid the deprecation message, you must convert all self, parent, and static keywords to their corresponding class names.
${var} String Interpolation
Here are some of the examples of variable values within a string literal with double quotes as allowed in PHP:
“$myname” – directly embedding variables.
“{$myname}” – braces outside the variable. “${myname}” – braces after the dollar sign. ” ${expr}” – variable variables equivalent to using (string) ${expr} |
As you can see, the last two variables are quite complex though they offer the same functionality. Given the complexity of variables, they are deprecated in PHP 8.2. Nonetheless, you can still execute the first two options without any issues.
The purpose of deprecated dynamic properties is to prevent mistakes and typos unless the class allows by opting for the #[\AllowDynamicProperties] attribute. Plus, with PHP 9.0, these deprecations will be upgraded to give exception errors.
Prevention of Passwords From Leaking Into Stack Traces & Error Logs:
Source: dinahosting.com
Currently, the standard feature code in many PHP codebases looks like this:
function connectToDatabase(
string $host, int $port, string $username, string $password) : void { // … } |
But as you can see, it poses a challenge when the function throws an uncaught exception, and as PHP’s stack traces include the values of function parameters, your password gets emitted to the error logs leading to security issues.
In the new PHP 8.2 update, you can add a new attribute that tags parameters as “sensitive.” So, when you apply the #[\SensitiveParameter] attribute, it will redact its value from stack traces:
function connectToDatabase(
string $host, int $port, string $username, #[\SensitiveParameter] string $password) : void { // … } |
Here’s an example of modified stack traces
#0 index.php(1): connectToDatabase(“localhost”, “3306”, “demo”, Object(SensitiveParameterValue))
#1 {main} |
Once you upgrade, you should audit your codebase to identify the sensitive values and add the attribute wherever required. Doing so will help you safeguard and enhance the security of the logs environment.
No Longer Support to libmysql from MySQLi:
If you have been using PHP for a long time now, you would know that it used to support two libraries in earlier days: mysqlnd and libmysql. However, since PHP 5.4 mysqlnd became the default recommended library.
Going a step further, with PHP 8.2, there is now only one library to connect your MySQL databases: mysqlnd.
Also Read: Apple’s Latest 16.3 Beta Releases: iOS, iPadOS, tvOS, WatchOS 9.3, & macOS Ventura 13
Sort Order Changes for the ksort Function
In PHP, ksort function is used to sort an array by key in ascending order, but PHP 8.2 has fixed the bug by prioritizing alphabetic keys before numeric keys.
So, in PHP 8.2, sorted keys will look like the following:
[“1″ => ”, “2” => ”, “a” => ”, , “b” => ”];
Instead of: [“a” => ”, “b” => ”, “1” => ”, , “2” => ”]; |
The str_split Function Returns Empty Arrays for Empty Strings
Though not a major update, with PHP 8.2, the str_split function will return an empty array if given an empty string. Earlier, it used to split a string into an array.
Also Read: ChatGPT-3: All You Need to Know about AI Chatbot Tool
Redact Sensitive Parameter Value Support
As we know that PHP allows users to track the call stack, knowing why an application may have failed makes more sense. Nonetheless, there will also be some stack traces that need to be masked, and for that, PHP 8.2 have added a new attribute called SensitiveParameter.
The sensitive parameter attribute prevents sensitive information from being shown or logged if an application is in trouble. Here’s an example of redact sensitive parameter value support:
function passwords(
$publicpassword, #[\SensitiveParameter] $secretpassword ) { throw new \Exception(‘Error’); } passwords(‘publicpassword’, ‘secretpassword’); |
New mysqli_execute_query Function and mysqli::execute_query Method
Last but not least, PHP 8.2 changes include an easier way to handle parameterized MySQLi queries. With this new change of the mysqli_execute_query($sql, $params) function and the mysqli::execute_query method, you can now prepare, bound, and execute queries within the same function.
Once you successfully run a query, you will get the mysqli_result object. Here’s an example of RFC’s proposed function:
foreach ($db->execute_query(‘SELECT * FROM user WHERE name LIKE ? AND type_id IN (?, ?)’, [$name, $type1, $type2]) as $row) {
print_r($row); } |
Summary:
There’s no doubt PHP 8.2 is a coder-friendly and exciting release containing usability improvements. All the PHP 8.2 updates are time-saving and advanced, including readonly classes, more flexible type definitions, constants in traits, enum values in constant expressions, and sensitive parameter value redaction for stack traces leading to smooth experiences for developers.
You can upgrade to the new PHP 8.2 through all the supported PHP distribution channels. The process of moving to 8.2 is simple and easy for codebases that are already in PHP PHP 8.x features and standards.
For more information regarding the latest technology, follow Techconcord.
Stay connected