When two traits define a method with the same name and you use both in the same class, PHP raises a fatal error. You must explicitly resolve the conflict using insteadof and as.
TraitA::method insteadof TraitB — use TraitA's version.
TraitB::method as aliasName — import the other version under a new name.
as can also change the visibility of a trait method.
Example
<?php
trait Logger
{
public function log(string $message): void
{
echo "[Logger] $message
";
}
public function format(string $text): string
{
return strtoupper($text);
}
}
trait Debugger
{
public function log(string $message): void
{
echo "[Debugger] " . date('H:i:s') . " $message
";
}
public function format(string $text): string
{
return "DEBUG: $text";
}
}
class Application
{
use Logger, Debugger {
// Conflict resolution for log()
Logger::log insteadof Debugger; // use Logger's log()
Debugger::log as debugLog; // also keep Debugger's as debugLog()
// Conflict resolution for format()
Debugger::format insteadof Logger; // use Debugger's format()
Logger::format as loggerFormat; // keep Logger's as loggerFormat()
}
}
$app = new Application();
$app->log('Application started'); // [Logger] Application started
$app->debugLog('Checking state...'); // [Debugger] 14:00:00 Checking state...
echo $app->format('hello'); // DEBUG: hello
echo $app->loggerFormat('hello'); // HELLO
// Change visibility with 'as'
trait Greet
{
public function hello(): string { return 'Hello!'; }
}
class Shy
{
use Greet {
hello as private; // make it private within this class
}
}
Pro Tip
Tip: When you find yourself resolving many trait conflicts, it is a sign the traits are too tightly coupled or overlapping in responsibility. Consider refactoring them into smaller, more focused traits or using composition instead.