Traits and interfaces both help with code reuse, but they solve opposite problems — an interface defines a contract with no implementation, while a trait provides actual implementation you can mix into unrelated classes.
Interfaces: Contracts
interface Loggable {
public function getLogMessage(): string;
}
class OrderCreated implements Loggable {
public function getLogMessage(): string {
return "Order created";
}
}
Traits: Shared Implementation
trait Timestampable {
private ?DateTime $createdAt = null;
public function touch(): void {
$this->createdAt = new DateTime();
}
}
class Post {
use Timestampable;
}
class Comment {
use Timestampable; // same behavior, unrelated class hierarchy
}
Use an interface when you need polymorphism (many classes, one contract). Use a trait when you need to share actual code across classes that have no logical inheritance relationship to each other.