haphpiness

These are things in PHP which make me genuinely_happy();

Typed Class Constants

PHP 8.3 brought type declarations to class constants — the last place in the language where types were missing. Now constants in classes, interfaces, traits, and enums can declare their type, and child classes can't accidentally change it.

interface HasVersion {
    const string VERSION = '1.0';  // Must be a string in all implementations
}

class Config implements HasVersion {
    const string VERSION = '2.0';     // OK — still a string
    const int MAX_RETRIES = 3;        // Typed constant
    const array DEFAULT_HEADERS = [   // Array type
        'Accept' => 'application/json',
        'X-Client' => 'php',
    ];
}

// Child classes can't violate the type contract
class BadConfig extends Config {
    const string MAX_RETRIES = 'three'; // Fatal error: type mismatch
}

// Works with all type declarations
class Limits {
    const int|string ID = 42;         // Union types
    const ?string LABEL = null;       // Nullable
    const true ENABLED = true;        // Literal types (PHP 8.2)
}

Before typed constants, an interface could declare const VERSION = '1.0' but had no way to prevent an implementing class from changing it to const VERSION = 42. Typed constants close this gap.

Significance: Completeness

With typed class constants, every part of a PHP class can now be typed: properties, parameters, return values, and constants. The type system is complete. This means static analyzers can verify your entire class contract, not just the parts that had type support.