A trait with a constant, and why I still avoid traits

Constants in traits arrived in 8.2 and the first thing I did with the feature was decide not to use it.

trait HasStatus
{
    public const DEFAULT = 'pending';   // 8.2

    public function status(): string { /* ... */ }
}

// the conflict rules, which are the reason to be careful:
// a class using two traits that both define DEFAULT is a
// fatal error, and insteadof does NOT resolve constants.
// there is no way to pick one.

The method conflict rules have an escape hatch and the constant rules do not, which makes a trait constant a name that can collide with no resolution available. That is a small thing on its own and it compounds the general problem: a trait is copy-paste with a compiler, and the more state it carries the harder it is to reason about what a class actually contains. An interface with a class constant, or composition, says the same thing without the collision.