A trait (PHP 5.4) is a bundle of methods and properties that PHP copies into every class that says use TraitName;. It is not a type and cannot be instantiated. A class may use several traits, and a trait may use others. When two traits bring the same method name, insteadof picks one and as keeps the other under an alias, optionally with new visibility. An abstract trait method demands something of the host class; PHP 8.0 enforces its signature.
<?php
trait Logs {
public function log(string $msg): string { return static::class . " log: $msg"; }
public function describe(): string { return 'describe() from trait Logs'; }
}
trait Audits {
abstract protected function actor(): string; // the host class must supply it
public function log(string $msg): string { return "audit by {$this->actor()}: $msg"; }
}
class Model { public function describe(): string { return 'describe() from Model'; } }
final class Order extends Model {
use Logs, Audits {
Audits::log insteadof Logs; // pick one log()
Logs::log as protected plainLog; // keep the other, renamed
}
protected function actor(): string { return 'admin'; }
public function save(): string { return $this->plainLog('saved'); }
}
$o = new Order();
echo $o->log('refund issued'), "\n", $o->save(), "\n", $o->describe(), "\n";audit by admin: refund issued Order log: saved describe() from trait Logs
The last line shows precedence: a class's own method beats a trait method, which beats an inherited one. Without insteadof, PHP stops with Trait method Audits::log has not been applied as Order::log, because of collision with Logs::log. In a trait, static::class and __CLASS__ name the using class.