Skip to content
Muhammet Şafak
tr
Languages 4 min read

PHP 8.3: Typed Class Constants and What's New

Typed class constants, json_validate, #[Override], and dynamic constant access in PHP 8.3 — the language's steady steps toward consistency.


PHP 8.3 is shipping at the end of this month. Before the release lands, I wanted to take a look at what it brings — starting from the beta package. 8.3 is not a major release — but that is precisely why it caught my attention. Its additions are focused on closing small inconsistencies the language had left open.

Typed Class Constants

For years, we could not declare a type on class constants. You could write private int $x on a property, but not on a constant. 8.3 fixes that:

class HttpDurum
{
    public const int BASARILI = 200;
    public const string VARSAYILAN_DIL = 'tr';
}

This might look like a cosmetic addition, but it guarantees that when a subclass redefines a constant, the type is preserved. It moves one more piece of the contract down to the compiler level.

Where Does the Real Value Show Up in Subclasses?

Typed constants become more meaningful once you factor in inheritance. When an interface or abstract class declares a typed constant, PHP now enforces that the implementing class keeps that constant at the correct type:

interface Raporlanabilir
{
    public const string FORMAT = 'text';
}

class PdfRapor implements Raporlanabilir
{
    // Valid — type matches
    public const string FORMAT = 'pdf';

    // This would be an error — string expected, not int
    // public const int FORMAT = 42;
}

Previously we expressed this with a documentation comment or a @var string PHPDoc annotation — the IDE understood it, but the runtime did not. Now both do.

The #[\Override] Attribute

The second addition is the #[\Override] attribute. It lets you declare that a method genuinely overrides a method from a parent class or interface:

class JsonRapor extends Rapor
{
    #[\Override]
    public function olustur(): string { /* ... */ }
}

If the method in the parent class is renamed or removed, PHP will throw an error because the annotated method no longer overrides anything. Previously, these kinds of silent breaks surfaced at runtime. Writing down the intent makes it enforceable.

You do not need to look at Java or Kotlin to appreciate this — it is a problem I have encountered many times in practice: a method in a parent class gets renamed during a refactor, the original-named method sitting in the subclass is no longer an override but a brand-new method, and nobody notices. #[\Override] turns that silent disconnect into a loud error.

json_validate()

Until now, to check whether a string was valid JSON, we called json_decode() and inspected the result — meaning we loaded the entire structure into memory just to throw it away. PHP 8.3 introduces json_validate(), a function that does validation only.

if (json_validate($gelenVeri)) {
    $decoded = json_decode($gelenVeri, true);
    // process
} else {
    // invalid JSON
}

For endpoints that accept large payloads, being able to reject invalid data without ever parsing it into memory is a meaningful win. It is especially useful for webhook receivers and batch-processing endpoints — in my tests, memory usage drops noticeably compared to calling json_decode purely for validation purposes.

Dynamic Constant Access

A small but long-awaited addition: you can now access a class constant using a variable:

$ad = 'BASARILI';
echo HttpDurum::{$ad};

Being able to do the same thing we have always done with properties and methods — but now with constants too — removes an asymmetry from the language. The practical use case: reading a constant name from a config file or database and accessing it dynamically. Before this, you would use constant() or reflection; now there is direct syntax for it.

My Takeaway from This Release

There is no showstopper feature in 8.3, but it shows how a mature language ages gracefully. New versions do not always have to bring sweeping paradigm shifts. Often the real value lies in the language quietly closing its own small inconsistencies.

Typed constants and #[\Override] hand off rules I used to maintain by hand or via comment to the language itself. The difference between leaving a rule to human discipline versus leaving it to the compiler: the former can get tired, the latter cannot.

Once the release is out, these two are the first things I plan to adopt in day-to-day code. json_validate() will come in handy almost immediately in an upcoming webhook project.

Looking at PHP’s last few releases, I see a pattern: 8.0 made a bold leap with union types and match expressions, 8.1 strengthened modeling with readonly and enums, 8.2 rounded that out with readonly classes, and 8.3 closes the remaining small inconsistencies. Each version builds on the one before, and the language’s overall coherence keeps growing. A language can mature without sweeping paradigm changes — PHP is showing that. PHP today and PHP a decade ago share a name and not much else.

Tags: #PHP
Share:

Comments

Sign in with your GitHub account to join the discussion. Comments are stored in GitHub Discussions.

Related Posts

Search the site

Start typing to search posts, projects and pages.

Esc to close Powered by Pagefind