Amit Merchant

Amit Merchant

A blog on PHP, JavaScript, and more

What's new in PHP 8.3 (Features and Improvements)

December 18, 2022 ·

PHP 8.3 is the next major release of the PHP programming language. It is scheduled to be released sometime in 2023.

And while PHP 8.2 was released a few days ago while writing this post, PHP 8.3 is already in the works. So, let’s take a look at what has been PHP 8.3 up to so far.

The new json_validate() function

PHP 8.3 will be introducing a new json_validate() function that can be used to validate a JSON string. So, we can do something like this.

$json = '{"name": "John Doe"}';
$valid = json_validate($json);

if ($valid) {
    // Valid JSON
} else {
    // Invalid JSON
}

Up until now, if we want to validate a JSON string in PHP, we can use the json_decode() function. Here’s how it works.

$json = '{"name": "John Doe"}';
$data = json_decode($json);

if (json_last_error() === JSON_ERROR_NONE) {
    // Valid JSON
} else {
    // Invalid JSON
}

The signature

The json_validate() function returns true if the JSON string is valid and false if it’s invalid. No more relying on the json_last_error() function. It’s far more readable, straightforward, and easy to use.

Here’s the exact signature of the json_validate() function.

json_validate(string $json, int $depth = 512, int $flags = 0): bool
  • $json - The JSON string to validate.
  • $depth - The maximum nesting depth of the structure being decoded. Must be greater than zero.
  • $flags - Bitmask of JSON decode flags. See the json_decode() function for more details.

Improved unserialize() error handling

PHP 8.3 will be improving the unserialize() function by throwing an UnserializationFailureException when the unserialize() function fails.

Previously, PHP would emit an E_NOTICE, an E_WARNING, or throw an arbitrary \Exception or \Error

This will make it easier to catch the error and handle it accordingly.

Before PHP 8.3, to successfully handle the exception, we had to do something like this.

try {
    set_error_handler(static function ($severity, $message, $file, $line) {
        throw new \ErrorException($message, 0, $severity, $file, $line);
    });
    $result = unserialize($serialized);
} catch (\Throwable $e) {
    // Unserialization failed. Catch block optional if the error should not be handled.
} finally {
    restore_error_handler();
}
 
var_dump($result);

As you can tell, we need to set an error handler, catch the exception, and then restore the error handler. This is a lot of work. And it’s not even guaranteed that the error handler will be restored correctly in case of an exception.

With PHP 8.3, we can do something like this.

try {
    $result = unserialize('B:2:"jon";');

    var_dump($result); 
    // Do something with the $result. 
} catch (\UnserializationFailureException $e) {
    // unserialization failed.
}

Essentially, a new \UnserializationFailedException will be added. Whenever a \Throwable is thrown during unserialize (e.g. within an __unserialize() handler or because a throwing error handler converts E_NOTICE/E_WARNING into an Exception), this \Throwable will be wrapped in a new instance of \UnserializationFailedException.

So, it’s a lot easier to handle an exception now. And we also don’t need to worry about using a custom error handler.

New methods in the Randomizer class

PHP 8.3 will be proposing new methods in the \Random\Randomizer class. These methods will open up new possibilities for generating random values.

The new getBytesFromString() method

The method allows you to generate a string with a given length that consists of randomly selected bytes from a given string.

public function getBytesFromString(string $string, int $length): string {}

Here’s how it works.

$randomizer = new \Random\Randomizer();

$randomizer->getBytesFromString('abcdef', 3); // 'bca'

As you can tell, the method will return a string with a given length that consists of randomly selected bytes from the given string.

Generating a multifactor authentication code

One interesting use case of this method is to generate a multifactor authentication code. Here’s how it works.

$randomizer = new \Random\Randomizer();

var_dump(
    implode('-', str_split($randomizer->getBytesFromString('0123456789', 20), 5))
);

// string(23) "09898-46592-79230-33336"

Generating random subdomain name

We can also generate a random subdomain name using this method.

$randomizer = new \Random\Randomizer();

var_dump(
    $randomizer->getBytesFromString('abcdefghijklmnopqrstuvwxyz', 10) . '.example.com'
);

// string(20) "jxqzjxqzjx.example.com"

Generating a DNA sequence

We can also generate a DNA sequence using this method.

$randomizer = new \Random\Randomizer();

var_dump(
    $randomizer->getBytesFromString('ATGC', 30)
);

// string(30) "TCTGCTGCTGCTGCTGCTGCTGCTGCTGCT"

The getFloat() method

The getFloat() method allows you to generate a random float number between two given numbers.

public function getFloat(
    float $min,
    float $max,
    IntervalBoundary $boundary = IntervalBoundary::ClosedOpen
): float {}

Here’s how it works.

$randomizer = new \Random\Randomizer();

$randomizer->getFloat(0, 1); // 0.123456789

As you can tell, the method will return a random float number between two given numbers.

Generating random latitude and longitude

We can use this method to generate random latitude and longitude.

$randomizer = new \Random\Randomizer();

var_dump(
    $randomizer->getFloat(-90, 90, \Random\IntervalBoundary::ClosedClosed),
    $randomizer->getFloat(-180, 180, \Random\IntervalBoundary::OpenClosed)
);

// Lat: float(-45.123456789)
// Long: float(123.123456789)

The nextFloat() method

The nextFloat() method allows you to generate a random float number between zero and one.

public function nextFloat(): float {}

Here’s how it works.

$randomizer = new \Random\Randomizer();

$randomizer->nextFloat(); // 0.123456789
$randomizer->nextFloat(); // 0.987654321

As you can tell, the method will return a random float number between zero and one. So, it’s essentially the same as the getFloat() method, but with a fixed range.

Simulate a coin flip

We can use this method to simulate a coin flip.

$randomizer = new \Random\Randomizer();

var_dump(
    $randomizer->nextFloat() > 0.5 ? 'Heads' : 'Tails'
);
// string(5) "Tails"

Simulate a dice roll

We can also use this method to simulate a dice roll.

$randomizer = new \Random\Randomizer();

var_dump(
    (int) ($randomizer->nextFloat() * 6) + 1
);
// int(3)

And that’s it for the new methods in the Randomizer class.

Fetch class constants dynamically

PHP has been supporting computed/dynamic properties and methods for a while now. I have discussed this in this article.

But to give you a gist of it, this is how it works.

$baz = 'foo';

$$baz = 'bar';
  ^
// $foo 

As you can tell, we can use the variable name as a variable name. So, we can dynamically create a variable name and then use it to create a variable.

Similarly, we can also call class methods dynamically like so.

class Foo 
{
   public function helloWorld()
   {
      echo 'Hello world!';
   }
}

$dynamicMethod = 'helloWorld';
$a = new Foo();
$a->{$dynamicMethod}(); //prints 'Hello world!'

But PHP did not support computed/dynamic class constants yet. This is something that PHP 8.3 will be proposing.

So, with PHP 8.3, we can access class constants dynamically like so.

class Foo 
{
   public const BAR = 'bar';
}

$dynamicConstant = 'BAR';

echo Foo::{$dynamicConstant}; 
//prints 'bar'

It handles the cases where trying to access a non-existent constant will throw an error.

class Foo {}
 
$bar = 'BAR';
echo Foo::{$bar};
// Error: Undefined constant Foo::BAR

You can read more about this in the RFC.

Learn the fundamentals of PHP 8 (including 8.1 and 8.2), the latest version of PHP, and how to use it today with my new book PHP 8 in a Nutshell. It's a no-fluff and easy-to-digest guide to the latest features and nitty-gritty details of PHP 8. So, if you're looking for a quick and easy way to PHP 8, this is the book for you.

👋 Hi there! I'm Amit. I write articles about all things web development. If you like what I write and want me to continue doing the same, I would like you buy me some coffees. I'd highly appreciate that. Cheers!

Comments?