Trait is something a class has. A trait doesn’t define a type of a class. For example, Teacher is a type. Talk a lot is a trait. A teacher can either talk a lot or not.
trait TalkALot { public function talk() { echo "I talk a lot"; } } class Teacher { private $name; public function __construct($name) { $this->name = $name; } use TalkALot; } $teacher = new Teacher("Oma"); $teacher->talk();
The code above will output “I talk a lot”
One class can implement multiple traits. However, those traits must not have same function name.
trait TalkALot { public function talk() { echo "I talk a lot"; } } trait TalkALittle { public funtion talk(){ echo "I don't talk"; } } class Teacher { private $name; public function __construct($name) { $this->name = $name; } use TalkALot, TalkALittle; } $teacher = new Teacher("Oma"); $teacher->talk();
The code above will cause an error:
Fatal error: Trait method talk has not been applied, because there are collisions with other trait methods on Teacher in C:\xampp\htdocs\lab\oop\index.php on line 21
You can use the keyword insteadof as a workaround in case your traits have same method name:
trait TalkALot { public function talk() { echo $this->name . " talk all days"; } } trait TalkALittle { public function talk() { echo $this->name . " talk a little"; } } class Teacher { private $name; use TalkALot, TalkALittle { TalkALittle::talk insteadof TalkALot; } public function __construct($name) { $this->name = $name; } } $teacher = new Teacher("Oma"); $teacher->talk();
What if you want to use the other method that get overridden?
trait TalkALot { public function talk() { echo $this->name . " talk all days"; } } trait TalkALittle { public function talk() { echo $this->name . " talk a little"; } } class Teacher { private $name; use TalkALot, TalkALittle { TalkALot::talk insteadof TalkALittle; TalkALittle::talk as modestTalk; } public function __construct($name) { $this->name = $name; } } $teacher = new Teacher("Oma"); $teacher->modestTalk();
Here, I’ve defined an alias for the talk method of TalkALittle trait. Then, I can call the talk method in TalkALittle trait as modestTalk.
Trait can have private function, just like class.
Since trait is something a class has, it has access to all class’s variable and methods
trait TalkALot { public function talk() { $this->requestSayName(); } } class Teacher { private $name; public function __construct($name) { $this->name = $name; } public function requestSayName() { echo "Say my name!"; } use TalkALot; } $teacher = new Teacher("Oma"); $teacher->talk();
As you can see, the function talk is in the trait TalkALot. The $teacher instance call it. The talk function call the function requestSayname, which is defined in the Teacher class.
You cannot define a property in a trait then define a property with the same name in the class
The following code generates an error:
trait TalkALot { private $name = "Trait"; public function talk() { $this->requestSayName(); } public function sayName() { echo $this->name; } } class Teacher { private $name; public function __construct($name) { $this->name = $name; } public function requestSayName() { echo "Say my name!"; } use TalkALot; } $teacher = new Teacher("Oma"); $teacher->sayName();
Fatal error: Teacher and TalkALot define the same property ($name) in the composition of Teacher. However, the definition differs and is considered incompatible. Class was composed in C:\xampp\htdocs\lab\oop\index.php on line 20
Trait can have static method. Static method in trait can access via the classes that use it either by class name or an instance:
trait TalkALot { public function talk() { echo $this->name . " talk all days"; } public static function tryTalking() { echo "bla bla <br />"; } } trait TalkALittle { public function talk() { echo $this->name . " talk a little"; } } class Teacher { private $name; use TalkALot, TalkALittle { TalkALot::talk insteadof TalkALittle; TalkALittle::talk as modestTalk; } public function __construct($name) { $this->name = $name; } } $teacher = new Teacher("Oma"); Teacher::tryTalking(); $teacher::tryTalking();
The above code prints two lines say “bla bla”