Two classes that need the same six lines and share no useful ancestor have left three options for as long as PHP has had objects: copy the lines, invent a base class whose only purpose is to hold them and spend the one inheritance slot on it, or delegate to a helper and wire it up twice. An interface never helped here — it declares a type and carries no code. Traits, new in 5.4, are the other half: code with no type.
interface Auditable
{
public function auditRecord();
}
trait RecordsAudit
{
abstract public function auditId();
public function auditRecord()
{
return array(
'class' => get_class($this),
'id' => $this->auditId(),
'at' => date('c'),
);
}
}
class Order implements Auditable
{
use RecordsAudit;
public function auditId()
{
return $this->id;
}
}
The abstract declaration inside the trait is what keeps it honest: a class that uses the trait without supplying auditId() is a fatal error when the class is compiled, not a missing method three screens into a request. The interface is still there because a trait is not a type and cannot be type hinted, so anything callers need to check on has to be declared twice — the interface for the signature, the trait for the body. Two rules are worth committing to memory. Precedence runs class, then trait, then parent, which is the reverse of most guesses. And two traits declaring the same method name is a fatal error until insteadof picks one. The real cost is that a trait can read the private properties of whatever uses it, so it is coupling that no signature declares and no search will reliably find.