When building class hierarchies where child classes may or may not override certain values, nullable class constants offer a clean pattern for fallback behavior.
By setting a parent constant to null and using PHP’s null coalescence operator (??), you create flexible inheritance without forcing every child class to define the same constant:
abstract class BaseReportJob
{
public const NAME = null;
abstract public function reportType(): string;
protected function getDisplayName(): string
{
// Falls back to reportType() if NAME is null
return static::NAME ?? $this->reportType();
}
}
class SalesReportJob extends BaseReportJob
{
public const NAME = 'Q4 Sales Report';
public function reportType(): string
{
return 'sales_report';
}
// getDisplayName() returns 'Q4 Sales Report'
}
class DataExportJob extends BaseReportJob
{
// Inherits NAME = null
public function reportType(): string
{
return 'data_export';
}
// getDisplayName() returns 'data_export'
}
Why this works:
- Child classes can optionally override
NAMEfor custom display values - Classes without a specific name fall back to their
reportType() - No need for multiple conditionals or checking
defined() - The
static::keyword ensures late static binding resolves the correct child constant
This pattern is especially useful for systems where some entities need custom branding while others use generic identifiers. The null coalescence keeps the logic clean and makes the fallback behavior explicit.
Alternative approaches:
You could achieve similar behavior with abstract methods, but constants are better when:
- The value is truly constant (won’t change at runtime)
- You want to access it statically:
SalesReportJob::NAME - Child classes don’t need complex logic to determine the value
For dynamic values that depend on instance state, stick with methods. For static configuration that some children override and others skip, nullable constants are perfect.
Leave a Reply