Constants in Traits
Traits could hold properties and methods but not constants, which is a strange gap once you notice it. A trait that encodes behavior around a fixed value had to keep the value somewhere else, and trust every consuming class to define it.
// Before 8.2: the trait needs a constant it cannot declare.
trait Retryable {
public function attempts(): int {
return static::MAX_ATTEMPTS; // hope the class defined this
}
}
class Job {
use Retryable;
// Forget this line and you get an Error at runtime, not at compile time.
public const MAX_ATTEMPTS = 3;
}
// 8.2: the trait carries its own constant, and its own default.
trait Retryable {
public const MAX_ATTEMPTS = 3;
public function attempts(): int {
return static::MAX_ATTEMPTS;
}
}
class Job {
use Retryable; // gets MAX_ATTEMPTS = 3
}
class StubbornJob {
use Retryable;
public const MAX_ATTEMPTS = 10; // override when you mean to
}
It is a small feature and it closes a real hole. A trait is supposed to be a unit of reuse you can drop into a class and have work. Requiring the consumer to remember an undocumented constant made that a lie, and the failure showed up at runtime in whichever code path happened to call the method.
Significance: Consistency Wins
Most of PHP's recent history is filling in squares of a grid. Classes have constants, interfaces have constants, enums have constants, and traits did not, for no reason a user could explain. Every gap like this is a rule someone has to memorize. Closing them means the language behaves the way you would guess, which is worth more than any single feature.