CodeBlanks Logo Icon CodeBlanks

Resolving method conflicts

PHP course · Intermediate · Lesson 62/115

Learn to resolve conflicts in traits with the same method name using insteadof and as.

Conflict on the same method name

If two traits contain a method with the same name and you use both, PHP throws a fatal error. You resolve the conflict with insteadof: you choose which trait's method wins.

class Report {
    use XmlReporter, CsvReporter {
        XmlReporter::format insteadof CsvReporter;
    }
}

Here format() calls XmlReporter's method; CsvReporter's method is suppressed.

Renaming with as (alias)

Sometimes you don't want the conflicting method to disappear; you want it reachable under a different name. For this you use as: it gives the method an alias.

use XmlReporter, CsvReporter {
    XmlReporter::format insteadof CsvReporter;
    CsvReporter::format as asCsv;
}

Now $r->format() returns XML, and $r->asCsv() returns CSV. Both methods are reachable.

Exercise Resolve the XmlReporter and CsvReporter conflict

Define an XmlReporter trait: its public function format(): string method does return "XML";. Define a CsvReporter trait: its public function format(): string method does return "CSV";. Then a Report class uses both and, in a use block, writes XmlReporter::format insteadof CsvReporter; and CsvReporter::format as asCsv;. With $r = new Report() call echo $r->format() . "\n" and echo $r->asCsv() . "\n".

Show example solution
:format insteadof CsvReporter; CsvReporter::format as asCsv; } }.
Example solution:
<?php
// Resolve the XmlReporter and CsvReporter conflict with insteadof and as
trait XmlReporter {
    public function format(): string {
        return "XML";
    }
}

trait CsvReporter {
    public function format(): string {
        return "CSV";
    }
}

class Report {
    use XmlReporter, CsvReporter {
        XmlReporter::format insteadof CsvReporter;
        CsvReporter::format as asCsv;
    }
}

$r = new Report();
echo $r->format() . "\n";
echo $r->asCsv() . "\n";

Test yourself

  1. Which keyword resolves a trait method conflict?

    • override
    • parent::
    • insteadof
    • final
    Show answer

    insteadof — Correct. insteadof picks which of two conflicting trait methods wins.

  2. Resolve the conflict with insteadof

    trait CacheA {
        public function store() { return "A"; }
    }
    trait CacheB {
        public function store() { return "B"; }
    }
    
    class Repo {
        use CacheA, CacheB {
            CacheA::store ____ CacheB;
        }
    }
    
    $r = new Repo();
    echo $r->store() . "\n";
    Show answer
    trait CacheA {
        public function store() { return "A"; }
    }
    trait CacheB {
        public function store() { return "B"; }
    }
    
    class Repo {
        use CacheA, CacheB {
            CacheA::store insteadof CacheB;
        }
    }
    
    $r = new Repo();
    echo $r->store() . "\n";
  3. After CacheA::store insteadof CacheB;, what does $r->store() return?

    • A
    • B
    • Fatal error
    • null
    Show answer

    A — Correct. insteadof makes CacheA win, so $r->store() returns A.

All lessons in Intermediate