What's New in PHP 8.3?

PHP 8.3 continues the language's strong momentum, delivering refinements that make everyday PHP development cleaner, safer, and more expressive. Whether you're upgrading an existing application or starting fresh, this guide walks you through the most important changes you should know.

Table of Contents

Typed Class Constants

One of the most-requested features finally lands in PHP 8.3: you can now declare types on class, interface, and enum constants.

interface HasVersion {
    const string VERSION = '1.0.0';
}

class Config implements HasVersion {
    const string VERSION = '2.5.1'; // Must be a string
    const int MAX_RETRIES = 3;
}

This enforces correctness at the class level and makes APIs more predictable. Before this, constants could silently hold the wrong type, causing subtle runtime bugs. Now, PHP throws a TypeError if a child class overrides a constant with an incompatible type.

The json_validate() Function

Developers have long relied on json_decode() followed by a json_last_error() check to validate JSON strings — a wasteful approach that parses the entire structure just to discard it. PHP 8.3 introduces a dedicated function:

$json = '{"name": "PHP Weekly", "version": 8}';

if (json_validate($json)) {
    echo "Valid JSON!";
} else {
    echo "Invalid JSON.";
}

This is significantly faster when you only need to verify validity without decoding, particularly useful in input validation pipelines and middleware layers.

Readonly Property Amendments

PHP 8.3 clarifies and expands the behavior of readonly properties. Notably, you can now reinitialize readonly properties during cloning by using clone with property overrides — a pattern that was previously impossible without reflection hacks.

class User {
    public function __construct(
        public readonly int $id,
        public readonly string $name,
    ) {}
}

$original = new User(1, 'Alice');
$clone = clone $original; // id and name carry over cleanly

Dynamic Class Constant Fetch

PHP 8.3 allows you to fetch class constants and enum members dynamically using a variable:

class Status {
    const ACTIVE = 'active';
    const INACTIVE = 'inactive';
}

$key = 'ACTIVE';
echo Status::{$key}; // Outputs: active

This mirrors the existing support for dynamic property and method access, making it easier to build configuration-driven or metadata-heavy systems.

Notable Deprecations to Watch

  • Passing negative $widths to mb_strimwidth() is now deprecated.
  • The u flag in range() with non-integer steps raises a deprecation warning.
  • Calling get_class() without arguments inside a static context is deprecated — use static::class instead.

Should You Upgrade?

PHP 8.3 is a stable, production-ready release. For most applications, upgrading from 8.2 is straightforward. Run your test suite with --deprecations warnings enabled, address any flagged calls, and you're likely good to go. The performance and safety gains make the upgrade well worth the effort.