Exploring the New Features and Enhancements in PHP 8.3: A Deep Dive into the Latest Updates (Part 1)

Backend Developer
3 min readAug 29, 2023

Hi to all php lover developers, in this article i will try to explain new features of newest version of PHP (8.3). There are many new features in 8.3 and this makes my default coding language more elegant and developer friendly. Nowadays php can easily use on desktop programming with Native PHP. Of course there were many other tools for using php in Desktop programming but i felt Native PHP is more cool then them. Anyway lets start diving to our new features.

1. Json Validation

I bet all of us try to validate a string if it is a json or not in sometime while developing new projects. This feature adds native method to php for validating string if it is a json or not. I know that’s very cool addition.

$json = '{ "example": "title" }';
$is_json = false;
if (json_validate($json)) {
// Valid JSON.
$is_json = true;
}

// Or better way
$is_json = json_validate($json);

Currently, most PHP programmers use the json_decode() function for this task, but this uses memory and processing power that isn’t required for just checking validity. There will be no need to use json_decode for validating a json string.

2. Improved unserialize() error handling

The error handling in unserialize() presently lacks consistency, as it has the potential to generate an E_NOTICE, E_WARNING, or even throw an unpredictable Exception or Error based on the nature of the improperly formatted input string. With new php feature will cover this issue.

Prior to the suggested modifications, the process of managing unserialization errors in PHP might resemble the following:

try {
set_error_handler(static function ($severity, $message, $file, $line) {
throw new \ErrorException($message, 0, $severity, $file, $line);
});

$result = unserialize($serialized);
} catch (\Throwable $e) {
// Optional catch block if you wish to handle the unserialization error.
} finally {
restore_error_handler();
}

var_dump($result);

After this feature we can use this way:

function unserialize(string $data, array $options = []): mixed
{
try {
// The existing unserialization logic happens here.
} catch (\Throwable $e) {
throw new \UnserializationFailedException(previous: $e);
}
}

And the implementation of UnserializationFailedException is :

class UnserializationFailedException extends \Exception
{
}

Is not it super cool! :)

3.Fetching Class Constants Dynamically

Before 8.3 we can not fetch class based constants by a variable. When we call those we should add constant name directly. Lets see how we fetch constants with current versions of php:

class StatusCodes {
const OK = 200;
const NOT_FOUND = 404;
const INTERNAL_ERROR = 500;
const UNAUTHORIZED = 401;
const FORBIDDEN = 403;
}

// Accessing the constants
echo StatusCodes::OK; // Output: 200
echo StatusCodes::NOT_FOUND; // Output: 404
echo StatusCodes::INTERNAL_ERROR; // Output: 500
echo StatusCodes::UNAUTHORIZED; // Output: 401
echo StatusCodes::FORBIDDEN; // Output: 403

With 8.3 we can use variables to fetch constants.

class StatusCodes {
const OK = 200;
const NOT_FOUND = 404;
const INTERNAL_ERROR = 500;
const UNAUTHORIZED = 401;
const FORBIDDEN = 403;
}
$variable = "OK";
// Accessing the constants
echo StatusCodes::{$variable} // Output: 200
$variable = "NOT_FOUND";
echo StatusCodes::{$variable} // Output: 404

With this we can call constants dynamically from a class, i loved this feature..

4.Introducing Read-Only Modifications

“The Objective of This Proposal: Overcoming the Restriction on Deep-Cloning Readonly Properties”

This proposal facilitates the reinitialization of readonly properties within the scope of the __clone() magic method invocation. Here’s an illustrative example of this enhancement:

Before 8.3:

class Example {
public readonly $readOnlyProp = 'Initial Value';
}

$instance = new Example();
$instance->readOnlyProp = 'New Value'; // this will not work



class Example {
public function __construct(
public readonly string $readOnlyProp,
) {}
public function __clone()
{
$this->readOnlyProp = clone $this->readOnlyProp; // Doesn't work, an error is thrown.
}
}

After 8.3

class Foo {
public function __construct(
public readonly string $example,
public readonly string $foo
) {}

public function __clone()
{
$this->example = clone $this->example; // Works.
$this->cloneFoo();
}

private function cloneFoo()
{
unset($this->foo); // Also works.
}
}

$foo = new Foo('Test', 'Example');

$foo2 = clone $foo;
// No error, Foo2::example is cloned deeply, while Foo2::$foo becomes uninitialized.

5. Typed Constants

As you all know before 8.3 we defined constants without specify a type. just like below:

class Example
{
const HTTP_STATUS_OK = 200;
}

You can now typehint class constants:

class Example
{
const int HTTP_STATUS_OK = 200;
}

--

--