Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

avoiding trait collisions - use_once?

I have two PHP traits that each inherit from the same 3rd trait:

trait C {
    public function smallTalk() {
        echo 'c';
    }
}

trait A {
    use C;
    public function ac() {
        echo 'a'.smallTalk();
    }
}

trait B {
    use C;
    public function bc() {
        echo 'b'.smallTalk();
    }
}

And I want to use them both in a class:

class D {
    use A, B;
    public function acbc() {
        echo ac().bc();
    }
}

but I keep getting the error

Fatal error: Trait method smallTalk has not been applied, because there are collisions with other trait methods on D

I know use_once is not a thing, but I am looking for the same functionality that require_once or include_once provides, but for traits. This example is simplified. My real C has lots of methods and is inherited by many more than 2 traits, so I don't really want to have to repeat a long string of insteadof every time I use more than 1 of these traits.

like image 247
wogsland Avatar asked Mar 28 '16 19:03

wogsland


1 Answers

You need read: Conflict Resolution

If two Traits insert a method with the same name, a fatal error is produced, if the conflict is not explicitly resolved.

To resolve naming conflicts between Traits used in the same class, the insteadof operator needs to be used to choose exactly one of the conflicting methods.

Since this only allows one to exclude methods, the as operator can be used to allow the inclusion of one of the conflicting methods under another name.

Example:

<?php
trait A {
    public function smallTalk() {
        echo 'a';
    }
    public function bigTalk() {
        echo 'A';
    }
}

trait B {
    public function smallTalk() {
        echo 'b';
    }
    public function bigTalk() {
        echo 'B';
    }
}

class Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
    }
}

class Aliased_Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
        B::bigTalk as talk;
    }
}
like image 63
Maxim Tkach Avatar answered Oct 24 '22 01:10

Maxim Tkach