Traits
Also Known As
PHP traits
trait keyword
horizontal reuse
TL;DR
Reusable code blocks that can be mixed into any class, providing horizontal code reuse without inheritance.
Explanation
PHP traits are a mechanism for code reuse in single-inheritance languages. A trait can contain methods (including abstract ones) and properties, and is included in a class with use TraitName. Conflicts between multiple traits are resolved explicitly. Traits are useful for cross-cutting concerns like logging, timestamping, or soft deletion. However, heavy trait usage can obscure where methods come from, increase coupling, and complicate testing — prefer composition (injected objects) for behaviour that varies, reserving traits for truly horizontal concerns.
Diagram
flowchart TD
subgraph Without_Traits
BASE2[Base class] -->|only one parent| CHILD[Child class<br/>cannot inherit from two classes]
end
subgraph With_Traits
T1[trait Timestampable<br/>created_at updated_at]
T2[trait SoftDeletable<br/>deleted_at restore]
T3[trait Auditable<br/>log changes]
MODEL2[Model uses T1 T2 T3<br/>all three behaviours]
T1 & T2 & T3 --> MODEL2
end
subgraph Conflict_Resolution
CONFLICT[Two traits same method] --> INSTEADOF[insteadof keyword<br/>choose which wins]
CONFLICT --> ALIAS[alias keyword<br/>rename one method]
end
style MODEL2 fill:#238636,color:#fff
style T1 fill:#1f6feb,color:#fff
style T2 fill:#6e40c9,color:#fff
Common Misconception
✗ Traits are a clean solution to the lack of multiple inheritance. Traits enable code reuse but create hidden coupling — a class using a trait implicitly depends on its internal details. Traits with state (properties) are especially fragile. Prefer composition via constructor injection for most reuse scenarios.
Why It Matters
Traits solve the horizontal code reuse problem PHP's single-inheritance model creates — you can compose behaviours like Timestampable, SoftDelete, or Auditable into any class without inheritance chains. Overusing them creates hidden coupling, but used well they eliminate duplication.
Common Mistakes
- Using traits as a substitute for proper abstraction — if the behaviour belongs in a service or base class, use that instead.
- Defining properties in traits that conflict with the using class — PHP raises a fatal error.
- Importing multiple traits with conflicting method names without resolving the conflict with insteadof.
- Hiding business logic in traits where it is hard to discover — traits are best for cross-cutting technical concerns.
Avoid When
- Do not use traits to work around poor class hierarchy design — if two classes share a trait's entire interface, they probably need a shared base class or interface.
- Avoid traits with more than one clear responsibility — they become hidden coupling between unrelated classes.
When To Use
- Use traits to share behaviour across classes that cannot share a common parent — horizontal code reuse.
- Use traits for cross-cutting concerns like logging, serialisation helpers, or timestamp management.
Code Examples
✗ Vulnerable
// Code duplication across unrelated classes:
class User {
public function getCreatedAt(): DateTime { return $this->createdAt; }
public function getUpdatedAt(): DateTime { return $this->updatedAt; }
}
class Product {
public function getCreatedAt(): DateTime { return $this->createdAt; } // Duplicated
public function getUpdatedAt(): DateTime { return $this->updatedAt; } // Duplicated
}
// With trait:
trait HasTimestamps {
public function getCreatedAt(): DateTime { return $this->createdAt; }
public function getUpdatedAt(): DateTime { return $this->updatedAt; }
}
class User { use HasTimestamps; }
class Product { use HasTimestamps; }
✓ Fixed
// Trait for shared behaviour across unrelated classes
trait Timestamps {
public ?\DateTimeImmutable $createdAt = null;
public ?\DateTimeImmutable $updatedAt = null;
public function touch(): void {
$this->updatedAt = new \DateTimeImmutable();
}
}
trait SoftDeletable {
public ?\DateTimeImmutable $deletedAt = null;
public function delete(): void { $this->deletedAt = new \DateTimeImmutable(); }
public function restore(): void { $this->deletedAt = null; }
public function isDeleted(): bool { return $this->deletedAt !== null; }
}
class Order { use Timestamps, SoftDeletable; }
class Product { use Timestamps; }
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
15 Mar 2026
Edited
31 Mar 2026
Views
32
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
No pings yesterday
Perplexity 9
Amazonbot 8
Ahrefs 5
Google 4
Unknown AI 2
ChatGPT 2
Also referenced
How they use it
crawler 26
crawler_json 4
Related categories
⚡
DEV INTEL
Tools & Severity
🟢 Low
⚙ Fix effort: Low
⚡ Quick Fix
Use traits for horizontal code reuse (logging, timestamping, soft-delete) across unrelated classes — but prefer composition/interfaces for behaviour that needs to be swappable
📦 Applies To
PHP 5.4+
web
cli
queue-worker
🔗 Prerequisites
🔍 Detection Hints
Identical methods duplicated across multiple classes with no common parent — candidate for trait
Auto-detectable:
✗ No
phpcpd
phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: Low
False Positives: High
✗ Manual fix
Fix: Medium
Context: Class
Tests: Update