In November of last year, PHP 8.3 was released. The new version includes a number of improvements — enhanced performance, better type compatibility, new features, and fixes for previously identified bugs. Let’s look at the most important changes that improved the quality of this release.
Type System
This area has always been one of PHP’s most sensitive parts, so with each release developers continue to gradually refine the type compatibility space. In this version, class constants can now be typed, and the mechanism for accessing class constants and Enum objects has been improved.
Typed Class Constants
In previous PHP versions, both the type and value of a constant declared inside a class could be radically changed in child classes or interfaces, which often led to confusion in the code and could cause serious errors.
For example, in older PHP versions:
class Testing_oldversion {
const string NEW_CONSTANT = 'oldversion';
}
class Testing_oldversion {
const string NEW_CONSTANT = [];
}Here, the NEW_CONSTANT not only “lost” its original value, but also changed from a string to an array — and yet, the interpreter continued execution without an error.
Starting from PHP 8.3, such overrides are no longer possible because class constants are now typed. If you try to change a constant’s type in a subclass or interface, the interpreter will throw a Fatal error and stop execution. This brings more predictability and consistency to your code — another step toward a more robust type system in PHP.
You can now declare a constant’s type directly after the const keyword, for example:
class Testing_newversion {
const string NEW_CONSTANT = 'newversion';
}
class Testing_newversion {
const string NEW_CONSTANT = [];
}
// Fatal error: Cannot use array as value for class constant Testing_newversion::NEW_CONSTANT of type stringAs you can see, the interpreter throws a fatal error and stops code execution.
Dynamic Access to Class Constants and Enum Objects
In earlier PHP versions, it was impossible to dynamically access class constants or Enum objects through a variable — the syntax ClassName::{$varName} wasn’t supported, and attempting to use it would result in a syntax error.
Old example:
enum OldEnum: int {
case OldMember = 30;
}
$enumName1 = 'OldMember';
echo OldEnum::{$enumName1}->value;Result:
Parse error: syntax error, unexpected token "->", expecting "("New example in PHP 8.3:
class NewClass {
public const NEW_CONST = 35;
}
$constName1 = 'NEW_CONST';
echo NewClass::{$constName1};The ClassName::{$varName} syntax is now valid, and the code executes without errors.
Proper Method Override in Classes or Interfaces
Before PHP 8.3, a developer could accidentally reuse a method name that already existed in a parent class or interface, leading to an unintended override.
To prevent this, PHP 8.3 introduces the #[\Override] attribute, which helps avoid accidental method overrides.
Now, overriding is only allowed if the attribute is explicitly declared before the method. If the attribute is present but no parent method exists, the interpreter throws a Fatal error.
Incorrect example:
class OneTest {
#[\Override]
public function newMethod(): void {}
}Result:
Fatal error: OneTest::newMethod() has #[\Override] attribute, but no matching parent method exists
Correct example:
class MainClass {
public function newMethod() {}
}
class ChildrenClass extends MainClass {
#[\Override]
public function newMethod() {}
}The attribute can also be used for Enum and Trait methods:
interface MainInterface {
public function oneMethod(): void;
}
enum ChildrenEnum implements MainInterface {
#[\Override]
public function oneMethod(): void {}
}
trait MainTrait {
#[\Override]
public function testMethod() {}
}
class NewClass {
use MainTrait;
public function testMethod(): void {}
}In both cases, the use of the attribute is valid and helps avoid common mistakes found in earlier PHP versions.
JSON Format Validation
PHP 8.3 introduces a new json_validate() function that checks whether a string conforms to JSON syntax.
Unlike json_decode(), this new function does not parse the string, so it uses significantly fewer CPU and memory resources.
Examples:
var_dump(json_validate('{ "onetesting": { "less": "moo" } }')); // true
json_validate(""); // false
json_validate("null"); // trueThe function does not return an error code, so you can still use json_last_error() and json_last_error_msg() for that purpose.
New Methods in the Randomizer Class
The Randomizer class, introduced in the previous PHP release, now includes new methods for generating random numbers in various formats.
Floating-Point Number Generation
The getFloat() and nextFloat() methods allow you to generate random floating-point numbers within a defined interval, without bias or rounding issues.
$rdm = new \Random\Randomizer();
$allvalue = $rdm->getFloat(
-5.2,
30.7,
\Random\IntervalBoundary::ClosedClosed,
);
$valueTrue = 0.1;
$mainBool = $rdm->nextFloat() < $valueTrue;
Generating Random Bytes
The getBytesFromString() method allows you to create strings composed of a specific number of bytes — useful for generating identifiers or random subdomains.
$rdm = new \Random\Randomizer();
$randomMyDomain = sprintf(
"%s.site.ua",
$rdm->getBytesFromString(
'abcdefghijk01234567',
7,
),
);
echo $randomMyDomain;
In this example, random subdomain names for site.ua are generated, consisting of seven random characters from a predefined set.
