PHP 8.3 and PHP 8.4 mark a turning point for the language, introducing features that fundamentally change how developers write robust, maintainable code. This guide dives deep into three key innovations — Typed Class Constants, Property Hooks, and json_validate — comparing them with earlier versions (8.0, 8.1, 8.2). If you are already familiar with modern PHP, you will understand how these additions eliminate workarounds, increase type safety, and simplify common operations. If you are an advanced beginner, you will find concrete examples to adopt them immediately.
Typed Class Constants in PHP 8.3
Typed class constants were introduced in PHP 8.3. Before this version, constants could only be declared without an explicit type; the type was inferred from the value, but could not be enforced. With PHP 8.3, you can specify the type, gaining greater static safety and clearer documentation.
Declaration and Benefits
The syntax is straightforward: add the type before the constant name:
class Status {
public const string DRAFT = 'draft';
public const string PUBLISHED = 'published';
public const int ACTIVE = 1;
}Before PHP 8.3, you could omit the type, leading to potential inconsistencies. In PHP 8.0 or 8.1, constants were always considered the same type as their value, but could not be checked by static analyzers. With explicit typing, tools like PHPStan or Psalm can catch errors during development.
Limitations and Use Cases
Typed constants support all primitive types (bool, int, float, string, array, null) and basic union types, but do not accept objects or classes as types (unless using the final constant construct from PHP 8.1). For enums, the type is implicit. A typical use case is defining configuration values or flags that must remain consistent:
class LoggerLevel {
public const string ERROR = 'error';
public const string WARNING = 'warning';
public const string INFO = 'info';
// If someone tries to assign a non-string value, PHP 8.3 throws a fatal error
}Property Hooks in PHP 8.4
Property Hooks are arguably the most disruptive feature in PHP 8.4. They allow you to add getter and setter logic directly where a property is declared, eliminating the need for magic methods like __get and __set. Before PHP 8.4, implementing computed or validated properties required separate interfaces or explicit get/set methods.
Basic Syntax
The syntax resembles languages like Kotlin or C#: after the property declaration, you add get and set blocks:
class User {
private string $firstName;
private string $lastName;
public function __construct(string $firstName, string $lastName) {
$this->firstName = $firstName;
$this->lastName = $lastName;
}
// Property Hook for fullName
public string $fullName {
get {
return $this->firstName . ' ' . $this->lastName;
}
set {
$parts = explode(' ', $value, 2);
$this->firstName = $parts[0];
$this->lastName = $parts[1] ?? '';
}
}
}In this example, $fullName is a virtual property: it has no storage of its own but reads and writes other properties. You can also declare properties with implicit backing store using only set or only get.
Advantages over __get/__set
Magic methods have two main problems: they are generic and do not allow explicit typing for each virtual property. With Property Hooks, every property can have its own logic with well-defined static types. Performance also improves because no interceptor function is involved.
PHP 8.4 also introduces the possibility of using Property Hooks in traits and interfaces (with declaration syntax), but concrete implementation is still evolving. For now, they are only allowed on public and protected properties.
json_validate in PHP 8.3
The json_validate function is a small but powerful addition in PHP 8.3. It solves a common problem: checking whether a string is valid JSON without fully decoding it. Before PHP 8.3, the only way was to call json_decode and then check json_last_error(), which allocated memory for the entire decoded object.
Usage
$jsonString = '{"name": "Mario"}';
// Old approach (PHP 8.0-8.2)
$decoded = json_decode($jsonString);
if (json_last_error() !== JSON_ERROR_NONE) {
// handle error
}
// New approach (PHP 8.3+)
if (!json_validate($jsonString)) {
// handle error
}
json_validate returns true if the string is valid JSON, false otherwise. It also accepts the second parameter $depth and third $flags, same as json_decode. It is especially useful in contexts like validating HTTP payloads, log entries, or configuration files where you only care about syntax, not the decoded object.
Performance Benefits
By not allocating the resulting data structure, json_validate is faster and uses less memory, especially for large JSON strings. It also avoids side effects of json_decode (e.g., creating stdClass objects).
Comparison with PHP 8.0, 8.1, 8.2
Versions 8.0, 8.1, and 8.2 introduced respectively: named arguments, readonly properties, enums, fibers, first-class callable syntax, and deprecations like get_parent_class() without arguments. However, they lacked the three features discussed here.
- Typed Class Constants: previously only documented via PHPDoc, now enforced by the language.
- Property Hooks: replace patterns like
__get/__setor explicit getter/setter methods, offering cleaner syntax. - json_validate: previously you used
json_decodewith error checking; now a dedicated function exists.
These improvements complete the modernization journey that started with PHP 8.0, making the language more expressive and safer.
Best Practices and Conclusion
Adopting these features requires careful planning, but the benefits are immediate:
- Use Typed Class Constants in all new classes that define public constants. For existing constants, add the type only if safe (watch for mixed values).
- Introduce Property Hooks when you need to add logic to a property without creating a separate get/set method. Avoid them for simple direct access.
- Replace
json_decode + error checkingwithjson_validatewhenever you only need to validate syntax. For actual decoding, continue usingjson_decode.
For related topics, check our Cybersecurity Guide for Web Developers and Laravel 11 & 12 Guide. External references: PHP 8.3 Migration Guide (official) and Property Hooks RFC.
Sponsored Protocol