PHP 8.3 introduced typed class constants, one of those small features that has a disproportionately positive impact on code quality. I've been using them extensively in production at DailyWatch, and they've caught several bugs that would have otherwise reached production.
The Problem Before Typed Constants
// PHP 8.2 and earlier - no type enforcement on constants
class CacheConfig {
const HOME_TTL = 10800; // Looks like an int, but no guarantee
const SEARCH_TTL = '21600'; // Oops, string instead of int. No error.
const CACHE_DIR = 123; // Completely wrong type. No error.
}
Constants could hold any type, and nothing prevented accidental type mismatches. These bugs often surfaced only at runtime, in edge cases.
PHP 8.3 Typed Constants
// PHP 8.3 - type enforcement at class load time
class CacheConfig {
const int HOME_TTL = 10800;
const int CATEGORY_TTL = 86400;
const int SEARCH_TTL = 21600;
const int WATCH_TTL = 21600;
const string CACHE_DIR = 'data/pagecache';
const bool ENABLED = true;
}
// This would cause a fatal error at class load time:
// const int SEARCH_TTL = '21600'; // TypeError!
Real-World Usage Patterns
Configuration Classes
class SiteConfig {
const string SITE_NAME = 'DailyWatch';
const string SITE_URL = 'https://dailywatch.video';
const int MAX_VIDEOS_PER_PAGE = 20;
const int FETCH_INTERVAL_SECONDS = 7200; // 2 hours
const bool DEBUG_MODE = false;
/** @var string[] */
const array REGIONS = ['US', 'GB', 'DE', 'FR', 'IN', 'BR', 'AU', 'CA'];
/** @var string[] */
const array FIXED_REGIONS = ['US', 'GB'];
}
HTTP Status Codes
class HttpStatus {
const int OK = 200;
const int NOT_FOUND = 404;
const int REDIRECT = 301;
const int SERVER_ERROR = 500;
}
Category Mapping
class VideoCategory {
const int FILM = 1;
const int AUTOS = 2;
const int MUSIC = 10;
const int PETS = 15;
const int SPORTS = 17;
const int GAMING = 20;
const int COMEDY = 23;
const int ENTERTAINMENT = 24;
const int NEWS = 25;
const int HOWTO = 26;
const int EDUCATION = 27;
const int SCIENCE = 28;
public static function name(int $id): string {
return match($id) {
self::FILM => 'Film & Animation',
self::MUSIC => 'Music',
self::GAMING => 'Gaming',
self::ENTERTAINMENT => 'Entertainment',
self::NEWS => 'News & Politics',
self::EDUCATION => 'Education',
self::SCIENCE => 'Science & Technology',
default => 'Other',
};
}
}
Database Migration Versions
class DatabaseVersion {
const int INITIAL_SCHEMA = 1;
const int ADD_FTS_INDEX = 2;
const int ADD_REGIONS_TABLE = 3;
const int ADD_BLOG_TABLES = 4;
const int ADD_API_KEYS_TABLE = 5;
const int CURRENT = 5;
}
Combining with Enums
Typed constants complement PHP 8.1 enums rather than replacing them. Use enums when you need a closed set of values, and typed constants when you need fixed configuration:
// Enum: closed set, type-safe in function signatures
enum Region: string {
case US = 'US';
case GB = 'GB';
case DE = 'DE';
case FR = 'FR';
}
// Typed constant: configuration values
class FetchConfig {
const int MAX_RESULTS = 50;
const int QUOTA_LIMIT = 10000;
const float BACKOFF_MULTIPLIER = 1.5;
}
The Bug That Typed Constants Caught
In the DailyWatch codebase, we had a cache TTL that was accidentally set as a float instead of an integer:
const int CACHE_TTL = 10800.0; // TypeError at class load!
// Without typed constants, this would silently pass and cause
// subtle issues with file_exists() time comparisons
This was caught during development, not at 2 AM in production. That alone justified the PHP 8.3 upgrade.
Typed constants are a small feature, but they enforce correctness at the foundation level of your application. If you're running PHP 8.3 in production (as we do at dailywatch.video), there's no reason not to add types to every class constant.
Top comments (0)