PHP 8.3: Let’s discuss the new features!

The PHP project publishes a new major or minor version of PHP at the end of each year. The authors announce a feature freeze around six months before the release; in the meantime, there's a flurry of activity as developers lobby for adoption of language modifications with every new release.

PHP 8.3 is releasing its new features on November 23 of this year. Like every time, they have included some amazing additions this time as well. Along with that, they are repudiating some of the vestiges from previous versions too.

We have compiled all that you need to know about these features in this article. So, read along!

Table Of Contents:-

PHP 8.3 New Additions

Let’s look at the new additions that have come in this year,

1. Typed class constants

PHP 8.3 introduces a new type declaration for class constants. This ensures type compatibility when child classes and interface implementations override them. From now, you can declare the type after const keyword.

class Test {
    const string TEST_CONSTANT = 'test';
}

Class constants support standard PHP standalone types, nullable types, union types, intersection types, and DNF types. But the following declarations are not allowed and tehy would return fatal error.

class Test {
    const void FOO = 'test';
    const never FOO = 'test';
    const callable FOO = 'test';
}
Fatal error: Class constant Test::FOO cannot have type void
Fatal error: Class constant Test::FOO cannot have type never
Fatal error: Class constant Test::FOO cannot have type callable

Further, you must remember that is a parent class declares a constant type, all the subclasses within it also must declare the same type .i.e., they cannot work without declaring any type.

class ParentClass {
    public const VALUE = 'MyValue';
}

class ChildClass extends ParentClass {
    public const VALUE = 'MyValue';
}
Fatal error: Type of ChildClass::VALUE must be compatible with ParentClass::VALUE of type string|int

2. json_validate() function

Prior to PHP 8.3, the only way to determine if a given string is a valid JSON string was to attempt to decode it, and see if any errors were emitted. The new json_validate function uses the same underlying JSON parser PHP uses, but consumes less memory and processing as json_decode only analyzes the string without constructing any decoded value.

But in the new update they have included the json_validate function, which returns a true or false value w.r.t. User input json strings.

json_validate('[1, 2, 3]'); // true
json_validate('{1, 2, 3]'); // false

Example of json_validate in action:

<?php

$jsonData = '{"name": "John", "age": 30, "email": "john@example.com"}';
$jsonSchema = '{"type": "object", "properties": {"name": {"type": "string"}, "age": {"type": "integer"}, "email": {"type": "string", "format": "email"}}}';

if (json_validate($jsonData, $jsonSchema)) {
    echo "JSON data is valid!";
} else {
    echo "JSON data is invalid.";
}

This function simplifies the validation process, reducing the complexity and potential errors associated with custom validation routines.

3. Dynamic class constant and Enum number fetch support

Earlier, you could not access class constants and enum numbers in PHP 3.8, but now you can use a variable name to do so.

class MyClass {
    public const MY_CONST = 42;
}

$constName = 'MY_CONST';
- echo \constant("MyClass::$constName");
+ echo MyClass::{$constName};

Similarly, for enum,

enum MyEnum: int {
    case MyMember = 42;
}

$enumName = 'MyMember';
- echo \constant("MyEnum::$enumName")->value;
+ echo MyEnum::{$enumName}->value;

The expression inside the {} is not limited to a variable name. Any expression that returns a string is allowed.

4. gc_status() now returns additional information

gc_status or garbage collector status in PHP returns statistics for running status, protection and buffer size. gc_status is usually required to optimize memory usage.

$gcStatus = gc_status();
echo "Total collected cycles: " . $gcStatus['cycles'];
echo "Memory usage before collection: " . $gcStatus['memoryUsageBefore'];
echo "Memory usage after collection: " . $gcStatus['memoryUsageAfter'];

As of now, when we run gc_status, it returns an array with four keys, but in the updated 8.3 version, eights keys are returned.

Field Type Description
Running Boolean True, if the garbage collector is running; False, otherwise.
Protected Boolean True, if the garbage collector is protected and root additions are forbidden; False, otherwise.
Full Boolean True, if the garbage collector buffer size exceeds GC_MAX_BUF_SIZE. This is currently set to 1024^3
buffer_time Integer Current garbage collector buffer size.
application_time Float Total application time in seconds, including collector_time
collector_time Float Time spent collecting cycles in seconds (includes destructor_time and free_time)
destructor_time Float Time spent executing destructors during cycle collection, in seconds
free_time Float Time spent freeing values during cycle collection, in seconds.

5. New \Random\Randomizer::getBytesFromString method

The \Random\Randomizer class in PHP 8.3 supports a new getBytesFromString method that returns a random number sequence of a requested length ($length parameter), only containing a bytes from the requested series of bytes ($string parameter).This method allows developers to obtain secure random bytes from a given string, providing a versatile and customizable approach to random data generation.

$rng = new Random\Randomizer();
$chars = 'AEIOU';
$rng->getBytesFromString($chars, 1); // "E"
$rng->getBytesFromString($chars, 5); // "AIIEO"
$rng->getBytesFromString($chars, 10); // "IEAUAIIOUE"

Note that the \Random\Randomizer::getBytesFromString() method works on the byte level. It cannot effectively shuffle multi-byte characters such as Emojis, CJK characters, and Eastern/Indo characters.

These methods allow developers to obtain high-precision random floating-point numbers within a specified range, enhancing the accuracy of random data.

6. New \Random\Randomizer::getFloat() and nextFloat() methods

Using \Random\Randomizer::getFloat() involves providing a minimum and maximum value, and the method generates a random floating-point number within that range.

Example: Generate a random number in the range 0 <= and < 1:

$rng = new Random\Randomizer();
$rng->nextFloat(); // 0.21185336351144

7. Fallback value support for PHP INI Environment Variable syntax

In PHP 8.3, PHP INI values can be substituted with feedback values if any particular environment variable is not set for it.

session.name = ${SESSION_NAME:-Foo}
sendmail_from = "${MAIL_FROM_USER:-info}@${MAIL_FROM_DOMAIN:-example.com}"
ini_get('session.name');
ini_get('sendmail_from');

the session.name value will be the value of the SESSION_NAME Environment variable if it is set, but it now uses Foo value otherwise.

sendmail_from value will also fall back to info@example.com if both MAIL_FROM_USER and MAIL_FROM_DOMAIN Environment variables are not set. If either of them are available, the Environment variable will be used.

8. PHP CLI Lint supports linting multiple files at once

PHP’s CLI allows linting to check a file name for syntax errors before executing. But the problem was that you could not lint multiple files together. How many ever files you passed, CLI linted only the first PHP file. This problem is sorted out in the new feature. Now, you can lint all the files in a single invocation.

  • If there is any file that was not accessible, the exit code will be 1.
  • If any of the files failed to lint, the exit code will be 255.
  • When both errors conditions are present, the exit code will be 1.

9. class_alias() supports aliasing built-in PHP classes

In PHP 8.3, the class_alias() function gains the ability to alias built-in PHP classes, which was not possible before. Using class_alias() to alias a built-in PHP class involves specifying the desired alias and the original class name as arguments. Once aliased, the original class can be referenced by its alias throughout the codebase.

class_alias(\DateTime::class, 'MyDateTime');
$customDateTime = new MyDateTime();

10. New stream_context_set_options function

PHP < 8.3 had a stream_context_set_option function which is used to support function signatures. It can either accept an array of options to set for one or more contexts or wrappers, or it can accept a single wrapper name, option name, or its value.

function stream_context_set_option($stream_or_context, string $wrapper, string $option, mixed $value): bool {
    // Function body (if any)
}
function stream_context_set_option($stream_or_context, array $options): bool {
    // Function body (if any)
}

Now, they have made  a new stream_context_set_options function (option changed to options), which will support the second signature function.

There is news that the first signature function will be deprecated in PHP 8.4 an further the earlier stream_context_set_option will be entirely removed in PHP 9.0.

PHP 8.3 Deprecations and Changes

1. get_class() and get_parent_class() changes

Like how you saw in the last paragraph, PHP is on a spree deprecating all those functions which were using more than one signature. get_class and get_parent_class functions accept an object $object parameter that returns the name of the class, or the name of the parent class. However, it also supports an alternative signature that, when no parameters are passed, it returns the name of the class in context.

class MyException extends InvalidArgumentException {
    public function __construct() {
        get_class();             // "MyException"
        get_parent_class();      // "InvalidArgumentException"
    }
}

In PHP 8.3, calling get_class and get_parent_class functions without parameters is deprecated. In PHP 9.0 the functionality allowing for the existence of multiple versions of a function with differing parameters will be eliminated. This means that if you don’t provide the $object parameter, you will get an error called ArgumentCountError.

2. unserialize(): E-NOTICE to E- WARNING

PHP provides serialize and unserialize function to serialize any PHP values to string and vice-versa. Previously, passing an invalid string to the unserialize() function emitted PHP notices (E_NOTICE) in certain cases, such as syntax errors. Since PHP 8.3, warnings (E_WARNING) are emitted instead. Moreover, certain error conditions of the serialize() function now emit E_WARNING. These include:

  1. Syntax errors
  2. Failures in the custom unserialize handlers using __unserialize magic method; e.g the __unserialize() method not returning any value
class Test {
	public function __unserialize(array $data) { } // Does not return anything
}

3. Returning the same variable twice from __sleep() magic method causing a name clash

class Test {
    public $foo = 'test';

    public function __sleep() {
        return array("foo", "foo"); // Same value returned twice
    }
}

serialize(new Test());

3. HTML Highlight tag changes

Syntax highlighting is supported by PHP's highlight_file and highlight_string functions. A file or string containing PHP code is accepted, and an HTML snippet containing PHP keywords, functions, and other tokens is returned. PHP INI directives control the colors of the syntax highlighter.

PHP 8.3 makes some changes to the syntax highlighter, resulting in changes to the resulting HTML output.

Additionally,

  • Output is now wrapped in <pre><code></code></pre>
  • Line-breaks no longer converted to <br /> tags
  • White spaces and tabs are no longer converted to HTML entities
<?php

function hello(): void {
    echo "Hello World";
}

hello();

echo highlight_string(string: $code, return: true);

How it comes on PHP < 8.3:

<code>
    <span style="color: #000000">
        <span style="color: #0000BB">&lt;?php<br /></span>
        <span style="color: #007700">function&nbsp;</span>
        <span style="color: #0000BB">hello</span>
        <span style="color: #007700">():&nbsp;</span>
        <span style="color: #0000BB">void&nbsp;</span>
        <span style="color: #007700">{<br />&nbsp;&nbsp;&nbsp;&nbsp;echo&nbsp;</span>
        <span style="color: #DD0000">"Hello&nbsp;World"</span>
        <span style="color: #007700">;<br />}<br /><br /></span>
        <span style="color: #0000BB">hello</span>
        <span style="color: #007700">();</span>
    </span>
</code>

How it comes in PHP 8.3:

<pre><code style="color: #000000">
    <span style="color: #0000BB">&lt;?php</span>
    <span style="color: #007700">function </span><span style="color: #0000BB">hello</span><span style="color: #007700">(): </span><span style="color: #0000BB">void </span><span style="color: #007700">{</span>
+    echo <span style="color: #DD0000">"Hello World"</span><span style="color: #007700">;</span>
+ }
+
+ </span><span style="color: #0000BB">hello</span><span style="color: #007700">();</span>
</code></pre>

4. Granular DateTime Exceptions

To better convey error and exception states, PHP 8.3 introduces extension-specific and granular Exception and Error classes. This makes it easier and cleaner to catch date-specific exceptions.

The new exception or error classes are added on top of existing \exception and \error classes and hence if your program already catches these errors, it will additionally catch any of these new errors as well.

Conclusion

In general, the PHP 8.3 version does not have any significant additions as compared to PHP 8.1 and 8.2.

This version has mostly concentrated on improving the language and aligning some features with how the language has evolved in the past several years. However, there are some tempting upgrades for developers and teams who know how to use them wisely.

With that said, if you have any queries about shifting to PHP 8.3, I would suggest you to go through the documentation carefully.


Atatus: PHP Performance Monitoring and Error Tracking

With Atatus, you can effectively monitor your PHP Application, providing a comprehensive view of transaction performance, tracking errors and exceptions, identifying slow database queries, monitoring delayed external requests, and offering function-level traces to pinpoint performance bottlenecks, among other features.

Atatus PHP monitoring, tracks and provides real-time notifications for every error, exception, and performance problem that occurs within the application. .

By tracking KPIs such as response times, throughput, HTTP failure rates, and error rates, it can help users identify and address any performance issues before they impact the application's users.

Furthermore, Atatus supports multiple PHP framework such as WordPress, Magento, Laravel, CodeIgniter, CakePHP, Symfony, Yii and Slim making it an adaptable tool that can be used to monitor applications across different frameworks and platforms.

Get started by trying our 14-day free trial of Atatus.