Skip to content

Traits in PHP

Last updated on September 17, 2015

Traits are one of the most powerful feature introduced in PHP 5.4. It allow us to write maximum reusable code. Traits are like Abstract class which cannot be instantiated on its own . Traits are just a collection of methods and we can import this methods into unrelated class at run time.

What is a Trait
A trait represents a collection of methods that can be used to extend the functionality of a class. Essentially a trait is similar to a class made only of concrete methods that is used to extend another class with a mechanism similar to multiple inheritance. As we already know PHP does not support multiple inheritance, wherever you require multiple inheritance you can use trait there, which reduces complexity and avoids the typical problems associated with multiple inheritance and Mixins.

A Trait can be a collection of other Traits, so one Trait can use one or more other traits. You can define abstract methods in Traits. We can also import or use Multiple Traits in a PHP Class.

Personally I do not recommend keeping multiple class or traits in one file instead of it use separate files for each Trait, this way we can organize code more elegant way and it allows maximum re-usability.

Trait Syntax

trait MyTrait {
 function traitMethod1() { // Method code }
 function traitMethod2() { // Method code }
}

// How to use 

class Test {
   use MyTrait;

}

$test = new Test;
$test->traitMethod1();

Abstract Methods in Traits
An abstract method can be declared in the trait by using the abstract keyword. In this case, the class using the trait has to implement the definition of the abstract method. The concept is same as Abstract method in Abstract class isn’t it.

trait ProjectScoreTrait {

// The class which uses this trait will have to implement this method
abstract public function getSecondOfScroe();
 
public function getScore() { // your score }
 
}
 
// Class Film Project Score
 
class FilmProject {
 
private $algorithmSettings;
 
use ProjectScoreTrait ;
 
// Class implements the Abstract method of Trait
public function getSecondOfScroe() { // your code here }
 
}
 
$filmProject = new FilmProject();
$filmProject->getScore(); 
 

NOTE : We know that in inheritance the private properties of a class can’t be accessed by child classes. Traits can access the private properties or methods of the composing classes, and vice versa.

Multiple Traits
So far we have used only one trait with a class, but in some cases we may need to incorporate the functionality of more than one trait.

sayHello() . " " . $world->sayWorld(); //Hello World

Nested Traits
The way a trait is used in a class, in the same way, the trait can be used in another trait. Thus, a trait A can be nested into another trait B and the methods and members of A can be accessed in the trait B and in the class using trait B.

	
trait A {

public function getFirstName() { }

}
 
trait B {

use A;

public function getLastName() { }

}
 
class Test {
 
use B;
 
}
 
$obj = new Test();
 
$obj->getFirstName();  // Method of Trait - A
 
$obj->getLastName(); // Method of Trait - B

To use multiple traits, you don’t always need to nest them. You can easily use multiple traits by comma-separating their names in the class. Ex : use traitName,TraitSecond; or use TraitName; use TraitSecond;

Changing Method Visibility
Using the as syntax, one can also adjust the visibility of the method in the exhibiting class.



Conflict Resolution
But now a problem will occur, if different Traits provide methods with the same name.

 

Both classes have to be used in a class named Talker. Multiple inheritance and Mixins define an algorithm to resolve this conflict. Traits don’t. Conflicts are not solved implicitly by any kind of precedence. Instead, to avoid implicit complexity, the developer has full control over class composition.

 

In case of the above definition of Talker, PHP will show a notice that there have been conflicts and name the methods smallTalk() and bigTalk() as the reason of this conflict. Therefore, neither of the given implementations will be available in the class.

Instead, the developer can exactly define which methods are used and how the conflict is resolved.


This definition will result in the exclusion of smallTalk() from the Trait A and bigTalk() from Trait B. Therefore, the resulting class Talker would echo “b” for smallTalk() and “A” for bigTalk(). But simple exclusion of methods is not the best choice for all situations.

 

Beside the exclusion an alias operation is available, too. This alias operation, notated like originalMethodName as additionalMethodName for arrays even has a similar semantics like the array notation. The definition A::bigTalk as talk lets the new name talk refer to the method body of bigTalk of the Trait B. The resulting Talker class will consist of following three methods:

bigTalk() { echo ‘A’; }
smallTalk() { echo ‘b’; }
talk() { echo ‘B’; }

Since the alias operation adds a new name to an existing method body, the bigTalk method still has to be excluded. Otherwise, PHP would print a notice that two methods from Traits have a conflict and are excluded. Aliasing is not renaming and references in methods to a given method name aren’t changed either. On the first look this may sound strange, but it provides the opportunity to build Traits and even hierarchies of Traits which fit together very well.

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments