Menu
Coddy logo textTech

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 occurred

The 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 icon

Challenge

Easy

Let'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 called EmailNotifier with a method notify(string $message) that returns "Email: [message]".
  • SmsNotifier.php — Create a trait called SmsNotifier with a method notify(string $message) that returns "SMS: [message]".
  • AlertService.php — Create an AlertService class that uses both traits. Since both traits have a notify() method, you'll need to resolve this conflict:
    • Use EmailNotifier::notify as the default notify() method
    • Create an alias notifyBySms for the SmsNotifier::notify method
    Also add a method notifyAll(string $message) that calls both notification methods and returns them combined on separate lines.
  • main.php — Include all the necessary files and create an AlertService instance. 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

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.

Cheat sheet

When multiple traits define methods with the same name, PHP requires explicit conflict resolution using insteadof and as operators.

The insteadof operator selects which trait's method to use as the default:

<?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"); // File: Error occurred
$app->logToDatabase("Error occurred"); // DB: Error occurred

The as operator creates an alias for a trait method, allowing access under a different name.

You can also use as to change method visibility:

<?php
trait Greeting {
    public function sayHello(): void {
        echo "Hello!";
    }
}

class Person {
    use Greeting {
        sayHello as private;
    }
}

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
?>
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming