Trait Conflict Resolution
Part of the Object Oriented Programming section of Coddy's PHP journey — lesson 53 of 91.
When two traits define methods with the same name, PHP throws a fatal error. You must explicitly tell PHP how to handle this conflict using the insteadof and as operators.
<?php
trait FileLogger {
public function log(string $message): void {
echo "File: $message";
}
}
trait DatabaseLogger {
public function log(string $message): void {
echo "DB: $message";
}
}
class Application {
use FileLogger, DatabaseLogger {
FileLogger::log insteadof DatabaseLogger;
DatabaseLogger::log as logToDatabase;
}
}
$app = new Application();
$app->log("Error occurred");
$app->logToDatabase("Error occurred");
Output:
File: Error occurred
DB: Error occurredThe insteadof operator chooses which trait's method to use when there's a conflict. In this example, FileLogger::log wins and becomes the default log() method. The as operator creates an alias, letting you access the other trait's method under a different name.
You can also use as to change a method's visibility:
<?php
trait Greeting {
public function sayHello(): void {
echo "Hello!";
}
}
class Person {
use Greeting {
sayHello as private;
}
}
This makes sayHello() private within the Person class, even though it's public in the trait. Conflict resolution gives you fine-grained control over how trait methods integrate into your classes.
Challenge
EasyLet's build a notification system where different channels can send messages, but we need to resolve conflicts when multiple traits provide the same method name.
You'll organize your code across four files:
EmailNotifier.php— Create a trait calledEmailNotifierwith a methodnotify(string $message)that returns"Email: [message]".SmsNotifier.php— Create a trait calledSmsNotifierwith a methodnotify(string $message)that returns"SMS: [message]".AlertService.php— Create anAlertServiceclass that uses both traits. Since both traits have anotify()method, you'll need to resolve this conflict:- Use
EmailNotifier::notifyas the defaultnotify()method - Create an alias
notifyBySmsfor theSmsNotifier::notifymethod
notifyAll(string $message)that calls both notification methods and returns them combined on separate lines.- Use
main.php— Include all the necessary files and create anAlertServiceinstance. You'll receive one input: a message string. Print three lines:- The result of calling
notify()with the message - The result of calling
notifyBySms()with the message - The result of calling
notifyAll()with the message
- The result of calling
This demonstrates how insteadof resolves which trait's method wins when there's a naming conflict, while as lets you keep access to the other trait's method under a different name.
Try it yourself
<?php
require_once 'AlertService.php';
// Read input
$message = trim(fgets(STDIN));
// TODO: Create an AlertService instance
// TODO: Print the result of calling notify() with the message
// TODO: Print the result of calling notifyBySms() with the message
// TODO: Print the result of calling notifyAll() with the message
?>This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe $this KeywordMethodsPropertiesConstructor (__construct)Destructor (__destruct)Recap - Simple Calculator4Inheritance
Basic InheritanceThe parent:: KeywordMethod OverridingThe final KeywordAbstract ClassesRecap - Employee Hierarchy7Encapsulation
Public, Protected, PrivateAccess Modifiers in DepthGetters and SettersInformation HidingConstructor Promotion (8.0)Recap - Student Records System2Namespaces & Autoloading
Introduction to NamespacesThe use KeywordPSR-4 Autoloading StandardComposer AutoloaderRecap - Organized Project5Interfaces & Contracts
Introduction to InterfacesImplementing InterfacesMultiple Interface ImplementInterface vs Abstract ClassType Hinting with InterfacesRecap - Shape Calculator8Magic Methods
Magic Methods Introduction__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Object Cloning__serialize & __unserializeRecap - Custom Collection11Type System & Error Handling
Type DeclarationsNullable TypesUnion & Intersection TypesException ClassesCustom Exception HierarchyTry, Catch, FinallyRecap - Form Validator14Project: Library Management
Project OverviewBook and User Classes3Class Properties
Instance vs Static PropertiesConstants in ClassesStatic Methods & PropertiesPrivate & Protected PropertiesReadonly Properties (PHP 8.1)Recap - Bank Account Manager6Polymorphism
Method Overriding RevisitedPolymorphism via InterfacesType Hinting & Union TypesLate Static BindingRecap - Payment Processor9Traits
Introduction to TraitsUsing Multiple TraitsTrait Conflict ResolutionAbstract Methods in TraitsTraits vs Inheritance12Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy Pattern