Traits — Horizontal Reuse (PHP 5.4)
debt(d7/e5/b7/t5)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints indicate automated detection is 'no' and the only listed tool is phpstan (a specialist static analyser). PHPStan can flag some trait misuse patterns but overuse, implicit host-class coupling, and unresolved conflicts are largely invisible without careful code review — they don't produce errors or warnings in typical CI unless specifically configured.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix advises preferring composition for complex shared behaviour and keeping traits small/self-contained. Removing a widely-used trait or untangling implicit host-class dependencies requires touching every class that uses the trait, potentially spanning multiple files across the codebase, making it more than a simple one-line or single-component fix.
Closest to 'strong gravitational pull' (b7). Traits apply to web, cli, and queue-worker contexts — all PHP contexts listed in applies_to. The why_it_matters note explicitly warns that overuse creates hidden coupling that's worse than duplication. A trait used across many unrelated class hierarchies becomes load-bearing: every class using it carries its implicit dependencies, and every future maintainer must understand those couplings when modifying either the trait or the host classes.
Closest to 'notable trap — a documented gotcha most devs eventually learn' (t5). The misconception field states developers conflate traits with interfaces, treating them as type contracts rather than reuse/implementation mechanisms. Additionally, common_mistakes highlight the non-obvious implicit coupling to host-class properties and the conflict-resolution requirement when multiple traits share method names — these are documented gotchas that most PHP developers discover through experience rather than intuition.
TL;DR
Explanation
Traits (PHP 5.4) allow including method groups in multiple classes: trait Timestampable { public function touch(): void { $this->updatedAt = new DateTime(); } }. Multiple traits per class with use Trait1, Trait2. Conflict resolution: insteadof and as operators. Traits can define abstract methods (requiring implementing class to provide them), properties, and constants (PHP 8.2). Downsides: traits create implicit coupling, make code harder to test (no mock boundary), and can lead to 'trait soup'. Prefer composition (inject a collaborator) when the trait becomes large or complex.
Common Misconception
Why It Matters
Common Mistakes
- Overusing traits as a workaround for lack of multiple inheritance — prefer composition.
- Traits that depend on specific properties of the host class — tight implicit coupling.
- Not resolving trait conflicts explicitly when using multiple traits with same method names.
Code Examples
// Trait depending on host class internals — implicit coupling:
trait Logger {
public function log(): void {
// Assumes $this->name exists in host class
echo $this->name . ' logged';
}
}
trait Timestampable {
private ?DateTime $updatedAt = null;
public function touch(): void {
$this->updatedAt = new DateTime();
}
public function getUpdatedAt(): ?DateTime {
return $this->updatedAt;
}
}