PHP 8.3 introduced several useful language improvements aimed at better type safety, cleaner object-oriented programming, easier JSON validation, and more flexible random data generation. The release includes features such as typed class constants, dynamic class constant fetching, the #[\Override] attribute, deep-cloning of readonly properties, and the new json_validate() function.
For developers maintaining modern PHP applications, these improvements can make code easier to understand, safer to refactor, and more convenient to maintain.
In this guide, we will explore the most useful PHP 8.3 features with practical examples.
What Is New in PHP 8.3?
PHP 8.3 is a major PHP language update that focuses on improving type safety, object-oriented programming, developer experience, and several standard-library capabilities.
Some of the most important additions include:
-
Typed class constants
-
Dynamic class constant fetch syntax
-
The
#[\Override]attribute -
Improved cloning support for readonly properties
-
The
json_validate()function -
Randomizer::getBytesFromString() -
New string and DOM functions
-
Additional reflection, socket, LDAP, ZIP, and POSIX improvements
The following sections focus on the features most likely to be useful in everyday PHP development.
1. Typed Class Constants in PHP 8.3
Before PHP 8.3, class constants could not explicitly declare their type.
For example:
class Application
{
public const VERSION = '1.0.0';
}
Although the value is a string, the constant itself did not explicitly communicate that requirement through a type declaration.
PHP 8.3 allows class constants to have scalar types such as string, int, float, and bool, as well as array.
Example
class Application
{
public const string VERSION = '1.0.0';
public const int API_VERSION = 3;
public const bool DEBUG = false;
}
Now PHP can enforce the declared type.
For example:
class Application
{
public const string VERSION = 100;
}
This results in a type error because the constant is declared as a string but receives an integer value.
Why Typed Constants Are Useful
Typed constants make the intention of your code clearer.
They are especially useful in:
-
Configuration classes
-
API version definitions
-
Application settings
-
Domain models
-
Framework components
-
Shared interfaces
For example:
interface PaymentGateway
{
public const string PROVIDER = 'stripe';
}
The declaration communicates the expected value type directly in the code.
Typed class constants also improve consistency when constants are inherited or implemented through interfaces. PHP 8.3 applies stricter checks around constant type compatibility and visibility.
2. Dynamic Class Constant Fetching
PHP 8.3 also introduced a cleaner syntax for accessing class constants dynamically.
Consider this class:
class AppConfig
{
public const string ENVIRONMENT = 'production';
public const string VERSION = '8.3';
}
You can store the constant name in a variable:
$name = 'VERSION';
PHP 8.3 allows you to fetch the constant using:
echo AppConfig::{$name};
The output is:
8.3
This provides a more direct syntax when the constant name is determined dynamically.
Practical Example
Suppose an application stores a configuration key:
class Settings
{
public const string APP_NAME = 'GizDevCraft';
public const string APP_VERSION = '1.0';
public const string APP_ENV = 'production';
}
$key = 'APP_NAME';
echo Settings::{$key};
Output:
GizDevCraft
This can be useful when building configuration systems, serializers, metadata handlers, and other dynamic application components.
3. The #[\Override] Attribute
One of the most useful object-oriented improvements in PHP 8.3 is the new #[\Override] attribute.
When a method is intended to override a method from a parent class or implement a method from an interface, you can explicitly mark it with #[\Override]. PHP will then verify that the method actually exists in the parent class or implemented interface.
Without #[\Override]
Consider:
class UserService
{
protected function saveUser(): void
{
// Save user
}
}
class AdminUserService extends UserService
{
protected function saveUsr(): void
{
// Intended to override saveUser()
}
}
There is a typo in saveUsr().
PHP treats it as a completely different method.
With #[\Override]
You can write:
class UserService
{
protected function saveUser(): void
{
// Save user
}
}
class AdminUserService extends UserService
{
#[\Override]
protected function saveUsr(): void
{
// ...
}
}
PHP will report an error because there is no matching parent method.
The correct implementation is:
class AdminUserService extends UserService
{
#[\Override]
protected function saveUser(): void
{
// Custom admin user saving logic
}
}
Why Use #[\Override]?
It helps:
-
Detect method-name typos
-
Make developer intent clearer
-
Improve refactoring safety
-
Prevent accidental method mismatches
-
Make large inheritance hierarchies easier to maintain
For large PHP applications, this small attribute can prevent subtle bugs during refactoring.
4. Deep-Cloning Readonly Properties
PHP introduced readonly properties before PHP 8.3, but cloning readonly objects had an important limitation.
PHP 8.3 allows readonly properties to be modified once inside the object's __clone() method, which makes deep cloning possible.
Consider:
class Profile
{
public function __construct(
public string $name
) {}
}
Now create a readonly class:
readonly class User
{
public function __construct(
public Profile $profile
) {}
public function __clone(): void
{
$this->profile = clone $this->profile;
}
}
Create an object:
$user = new User(
new Profile('Ram')
);
Then clone it:
$copy = clone $user;
The nested Profile object can now be cloned separately.
Why Is Deep Cloning Important?
Consider an object containing another mutable object:
User
└── Profile
└── Name
A normal object clone can result in both objects referring to the same nested object.
Deep cloning creates an independent nested object:
Original User
└── Profile A
Cloned User
└── Profile B
This is useful when working with immutable or readonly domain objects that contain mutable object references.
5. json_validate() in PHP 8.3
PHP 8.3 introduced the json_validate() function for checking whether a string contains syntactically valid JSON.
Previously, developers commonly used json_decode() simply to determine whether JSON was valid.
For example:
$json = '{"name":"Ram","age":30}';
json_decode($json);
if (json_last_error() === JSON_ERROR_NONE) {
echo 'Valid JSON';
}
PHP 8.3 provides a much simpler approach:
$json = '{"name":"Ram","age":30}';
if (json_validate($json)) {
echo 'Valid JSON';
} else {
echo 'Invalid JSON';
}
Invalid JSON Example
$json = '{"name":"Ram",}';
var_dump(json_validate($json));
Output:
bool(false)
Valid JSON Example
$json = '{"name":"Ram","age":30}';
var_dump(json_validate($json));
Output:
bool(true)
The function returns a boolean indicating whether the supplied string contains valid JSON. It can also accept a maximum depth and flags.
When Should You Use json_validate()?
json_validate() is useful when you only need to know whether JSON is valid and do not need the decoded data.
For example:
function isValidJson(string $json): bool
{
return json_validate($json);
}
This can be useful for:
-
API request validation
-
Configuration validation
-
Webhook payload checks
-
Import validation
-
JSON form fields
-
Queue messages
Important Performance Consideration
Do not automatically call json_validate() before json_decode().
For example, this is unnecessary:
if (json_validate($json)) {
$data = json_decode($json, true);
}
The JSON will effectively be processed twice.
The PHP documentation specifically notes that json_validate() is most useful when you need to check validity but do not need to decode the JSON immediately.
If you need the decoded data, simply decode it directly.
6. Generate Random Strings with Randomizer::getBytesFromString()
PHP 8.2 introduced the new Random extension, and PHP 8.3 added Randomizer::getBytesFromString(). This method makes it easier to generate random strings using characters from a specified set.
Example:
$randomizer = new \Random\Randomizer();
$code = $randomizer->getBytesFromString(
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
12
);
echo $code;
A possible result could be:
A7K9X2P4M8Q1
This can be useful for generating:
-
Random identifiers
-
Short codes
-
Test data
-
Nonces
-
Random strings
-
Human-readable identifiers
The PHP release documentation notes that the default engine is secure, while a different Random\Engine can be supplied when deterministic output is needed for testing.
7. Other Useful PHP 8.3 Improvements
PHP 8.3 contains many additional changes beyond the major features discussed above.
The release added new functionality across several extensions, including DOM, Intl, LDAP, POSIX, Reflection, sockets, strings, streams, and ZIP. It also added support for readonly anonymous classes and new configuration capabilities.
Some notable additions include:
New String Functions
PHP 8.3 adds:
str_increment()
str_decrement()
str_pad()
The new str_increment() and str_decrement() functions can be useful for incrementing or decrementing alphanumeric strings.
New mb_str_pad()
Developers working with multibyte strings can use:
mb_str_pad()
for multibyte-aware padding.
New DOM APIs
PHP 8.3 adds several DOM-related methods, including methods for working with attributes, elements, nodes, and child replacement.
These improvements are particularly useful for applications that manipulate HTML or XML documents.
PHP 8.3 Example: Combining Several Features
Here is a small example combining typed constants, #[\Override], and json_validate():
interface ApiResponse
{
public const string FORMAT = 'json';
public function validate(string $payload): bool;
}
class JsonResponse implements ApiResponse
{
#[\Override]
public function validate(string $payload): bool
{
return json_validate($payload);
}
}
$response = new JsonResponse();
$json = '{"status":"success","message":"Hello"}';
if ($response->validate($json)) {
echo 'Valid ' . ApiResponse::FORMAT . ' response';
}
Output:
Valid json response
This example demonstrates how several PHP 8.3 features can work together in a real application structure.
PHP 8.3 Migration Considerations
Before upgrading a production application to PHP 8.3, test the application in a staging environment.
Pay particular attention to:
-
Deprecated functionality
-
Changes in error behavior
-
Third-party package compatibility
-
Framework compatibility
-
Database extensions
-
PHP extensions used by your application
-
Changes in type checking
-
Readonly object behavior
-
Existing class constants
PHP 8.3 also includes backward-compatibility changes and deprecations, so developers should review the official migration documentation before upgrading a production system.
Common Mistakes When Using PHP 8.3 Features
1. Using json_validate() before every json_decode()
If you are going to decode the JSON immediately, validating it first can result in unnecessary duplicate parsing.
Use json_validate() when you only need to check validity.
2. Adding #[\Override] to unrelated methods
The attribute is specifically for methods or properties that override or implement something from a parent class or interface.
#[\Override]
protected function calculateTotal(): float
should only be used when a matching parent/interface member exists.
3. Assuming readonly means every nested object is immutable
A readonly property prevents reassignment of the property itself, but an object stored in that property can have its own mutable state.
Deep cloning may therefore be necessary when independent object state is required.
4. Declaring overly restrictive constant types
Typed constants should represent the actual contract of the application.
For example:
public const string VERSION = '1.0';
is useful when the constant must always be a string.
5. Using new features without checking the server version
Features such as json_validate() require PHP 8.3 or newer. The PHP manual documents json_validate() as available from PHP 8.3.0.
Check your PHP version with:
php -v
PHP 8.3 vs Earlier PHP Versions
| Feature | Older PHP | PHP 8.3 |
|---|---|---|
| Typed class constants | Not available | Available |
| Dynamic class constant fetch | Older syntax required | Class::{$name} |
#[\Override] |
Not available | Available |
| Readonly deep cloning | Limited | Improved |
json_validate() |
Not available | Available |
Randomizer::getBytesFromString() |
Not available | Available |
| Additional standard-library improvements | — | Added |
PHP 8.3 therefore provides several improvements that can make modern applications more expressive and type-safe.
Frequently Asked Questions
What are the main features of PHP 8.3?
The major PHP 8.3 features include typed class constants, dynamic class constant fetching, the #[\Override] attribute, improved readonly property cloning, json_validate(), and Randomizer::getBytesFromString().
What is json_validate() in PHP 8.3?
json_validate() checks whether a string contains syntactically valid JSON and returns either true or false. It is useful when you need validation without decoding the JSON payload.
Can PHP 8.3 class constants have types?
Yes. PHP 8.3 allows class constants to declare types such as string, int, float, bool, and array.
What does #[\Override] do in PHP?
The #[\Override] attribute tells PHP that a method or property is intended to override or implement a member from a parent class or interface. PHP reports an error if no matching member exists.
What changed with readonly properties in PHP 8.3?
PHP 8.3 allows readonly properties to be reassigned once during __clone(), enabling deep cloning patterns for objects containing readonly properties.
Does json_validate() decode JSON?
No. It checks whether the JSON syntax is valid and returns a boolean. If you need the actual data, use json_decode() instead.
Is PHP 8.3 worth upgrading to?
For applications that can support the new version, PHP 8.3 provides useful language improvements, better type safety, new APIs, and developer-friendly features. Production upgrades should still be tested carefully for framework, library, extension, and backward-compatibility issues.
Conclusion
PHP 8.3 is an important update for developers building and maintaining modern PHP applications.
The most useful improvements include typed class constants, dynamic class constant fetching, the #[\Override] attribute, deep cloning of readonly properties, and json_validate(). The new Randomizer::getBytesFromString() method and additional standard-library improvements also make everyday development easier.
For developers working on large applications, these features are more than syntax improvements. Typed constants make contracts clearer, #[\Override] helps catch refactoring mistakes, readonly cloning provides better control over object state, and json_validate() provides a straightforward way to validate JSON when decoding is unnecessary.
If you are upgrading an existing application, test your code and dependencies carefully and review the official PHP migration documentation before deploying PHP 8.3 to production.
Related PHP Topics:
-
PHP 8.3 typed class constants
-
PHP
json_validate() -
PHP readonly properties
-
PHP
#[\Override] -
PHP
Randomizer -
PHP object cloning
-
PHP type safety
-
Modern PHP development
Discussion (0)
Sign in to join the discussion
Only registered developers with verified email addresses can leave comments.
No comments yet. Be the first to start the conversation!