PHP 8.3 shipped on 23 November 2023, and rather than reinventing the language it delivered dozens of practical improvements that smooth out everyday development. The highlights include typed class constants for stronger type safety, the json_validate() function for cheap JSON validation, the #[\Override] attribute that catches inheritance mistakes early, and a handful of quiet performance gains. In this article we walk through the changes that will actually help you, with real, runnable code.
Typed class constants: constants are finally type-safe
For years PHP refused type declarations on constants. A subclass could redefine an inherited constant with the wrong type, and the mistake only surfaced at runtime — in the worst case, in production. PHP 8.3 lets you declare a type on class, interface, trait and enum constants.
interface Colored
{
const string DEFAULT = 'blue';
}
class Card implements Colored
{
// Error: type mismatch (string expected, int given)
// const string DEFAULT = 0xFF;
const string DEFAULT = 'red';
}
The key detail: a child constant must stay compatible with the type defined in the parent. If a constant is typed int, an inheriting class cannot turn it into a string. In large codebases this makes contracts far more reliable.
json_validate(): check validity without wasting memory
Previously, the only practical way to know whether a string was valid JSON was to call json_decode() and inspect for errors. But that built an entire PHP data structure in memory even when all you wanted was a yes/no answer. json_validate() fixes exactly that waste: it parses but builds nothing, and simply tells you whether the input is valid.
$raw = '{"name":"Aslain","langs":["tr","en","de"]}';
if (json_validate($raw)) {
$data = json_decode($raw, true);
// process safely
} else {
// malformed body — return 400
}
This is most valuable when you only need to filter webhook bodies, API requests or large user-supplied payloads by "is this valid?". When you actually need the contents, you still call json_decode().
The #[\Override] attribute: let the engine verify your overrides
You think you are overriding a parent method, but there is a small typo in the name; instead of overriding you have defined a brand-new method, and the bug vanishes silently. PHP 8.3's #[\Override] attribute eliminates this whole class of error: you declare that a method genuinely comes from a parent type, and if it does not, PHP raises a fatal error.
class BaseQueue
{
public function process(): void {}
}
class RedisQueue extends BaseQueue
{
#[\Override]
public function process(): void
{
// guaranteed to actually override
}
}
The attribute is priceless in code that implements interfaces or has deep inheritance chains. The moment a parent renames a method, every subclass carrying #[\Override] screams immediately, preventing a silent regression before it happens.
Dynamic class constant fetch and new string helpers
Before PHP 8.3, holding a constant's name in a variable and accessing it dynamically meant indirect tricks like constant(). Now you can access it directly with curly-brace syntax:
class Status
{
const ACTIVE = 'active';
const INACTIVE = 'inactive';
}
$field = 'ACTIVE';
echo Status::{$field}; // "active"
Two small but handy functions also arrived for string generation: str_increment() and str_decrement(). They increment and decrement alphanumeric strings sensibly, the way a licence plate or serial number rolls over:
echo str_increment('Az'); // "Ba"
echo str_increment('A9'); // "B0"
echo str_decrement('B0'); // "A9"
Readonly cloning and Randomizer additions
The readonly properties introduced in PHP 8.2 were powerful but had one limitation: you could not change their value while cloning. PHP 8.3 lifts that — you can now reinitialize a readonly property inside __clone(). This makes "with"-style copies of immutable objects far cleaner.
final class Money
{
public function __construct(
public readonly int $cents,
) {}
public function __clone(): void
{
// reassignment allowed during cloning
}
}
On the randomness side, the Random\Randomizer class gained new methods: getFloat(), nextFloat() and getBytesFromString(). They offer one-line, bias-free ways to generate a random string from a given alphabet (passwords, tokens or coupon codes) or a float within a controlled range.
Performance and other small touches
PHP 8.3 does not claim a dizzying speed jump, but engine- and JIT-level improvements bring stable, measurable gains on typical web workloads. A few other notable items stand out:
- Stack overflow protection:
zend.max_allowed_stack_sizelets deep or infinite recursion stop with a clean error instead of a segfault. - More precise Date/Time exceptions: date classes now throw specific exceptions such as
DateMalformedStringExceptioninstead of a genericException. DateTime::createFromTimestamp(): a new static method to build a date object directly and readably from a timestamp.- Anonymous readonly classes: you can now write
new readonly class { ... }.
Practical advice: if you are starting a new project, pick PHP 8.3 (or newer) outright. On an existing Laravel or plain PHP project, first bump the version constraint in composer.json, then run your test suite; because 8.3 is largely backward compatible, the migration is usually painless.
Frequently Asked Questions
Is upgrading from PHP 8.2 to 8.3 hard?
In most cases, no. PHP 8.3 introduces few breaking changes; the main new features are additive. Still, the safest path is to run your automated tests and confirm 8.3 support for the packages you depend on before going to production.
Is json_validate() always faster than json_decode()?
Its real advantage is memory: json_validate() builds no PHP data structure, so it uses less memory on large payloads. But if you actually need the data, you still call json_decode() afterwards — in which case decoding once and checking for errors may make more sense than two calls.
Do typed constants break existing constants?
No. The type declaration is optional; your current untyped constants keep working exactly as before. You can add types gradually, only where you want the extra guarantee.
Want to modernize your PHP stack? Let's work together on a Laravel or plain PHP upgrade to 8.3, with type safety and a performance review. Get in touch and let's talk through your project.