Trait in PHP 5.4

By Avinash

November 09, 2011Tutorial18 Comments

What is trait?

Trait is the new concept introduced in PHP 5.4. Which likes to remove the limitation of the multiple inheritance in single inheritance language PHP.

Before PHP 5.4, PHP support single inheritance and multiple interface but trait is going to remove the limitation of not having multiple inheritance.

Why Use trait?

The main concept behind the trait is the reusability of the code. trait seems to be very useful in terms of code reusability for the in language which supports only single inheritance like PHP.

So main reason to use the trait is to gain the benefits of multiple inheritance and alternatively of the code reusability.

How to Use trait?

Trait can be initialized with the keyword trait.

Let’s see how to start with the trait:

trait first_trait { function first_method() { /* Code Here */ } function second_method() { /* Code Here */ } }
  trait first_trait
  {
    function first_method() { /* Code Here */ }
    function second_method() { /* Code Here */ }
  }

Trait can be used within class using use keyword.

class first_class { // Using the Trait Here use first_trait; } $obj = new first_class(); // Executing the method from trait $obj->first_method(); // valid $obj->second_method(); // valid
  class first_class
  {
    // Using the Trait Here
    use first_trait;
   
  }
 
  $obj = new first_class();
 
  // Executing the method from trait
  $obj->first_method(); // valid
  $obj->second_method(); // valid

Make note that we can not create an object of the class using new keyword just like class.

Using Multiple trait

We can use multiple trait in a class. So here is what we can consider as a multiple inheritance.

So any class which uses the multiple trait will have all methods available in both trait.

Let’s see how it works:

trait first_trait { function first_method() { echo "method1"; } } trait second_trait { function second_method() { echo "method2"; } } class first_class { // now using more than one trait use first_trait, second_trait; } $obj= new first_class(); // Valid $obj->first_method(); // Print : method1 // Valid $obj->second_method(); // Print : method2
  trait first_trait
  {
    function first_method() { echo "method1"; }
  }
 
  trait second_trait
  {
    function second_method() { echo "method2"; }
  }

  class first_class
  {
    // now using more than one trait
    use first_trait, second_trait;
  }
 
  $obj= new first_class();
 
  // Valid
  $obj->first_method(); // Print : method1
 
  // Valid
  $obj->second_method(); // Print : method2

Trait Contains the Trait

Here one more interesting thing is the we can use the trait inside another trait. We can say this as a extending the trait.

trait first_trait { function first_method() { echo "method1"; } } trait second_trait { use first_trait; function second_method() { echo "method2"; } } class first_class { // now using use second_trait; } $obj= new first_class(); // Valid $obj->first_method(); // Print : method1 // Valid $obj->second_method(); // Print : method2
  trait first_trait
  {
    function first_method() { echo "method1"; }
  }
 
  trait second_trait
  {
    use first_trait;
    function second_method() { echo "method2"; }
  }

  class first_class
  {
    // now using
    use second_trait;
  }
 
  $obj= new first_class();
 
  // Valid
  $obj->first_method(); // Print : method1
 
  // Valid
  $obj->second_method(); // Print : method2

Note: trait can not be initialized with the keyword new same as class.

Abstract Methods in Trait

We can declare abstract method in trait. So after declaring the abstract method in trait, as class must have to implement that method which uses that trait. This is the same concept as the abstract class and abstract method.

trait first_trait { function first_method() { echo "method1"; } // any class which use this trait must // have to implement below method. abstract public function second_method(); } class first_method { use first_trait; function second_method() { /* Code Here */ } }
  trait first_trait
  {
    function first_method() { echo "method1"; }
    // any class which use this trait must
    // have to implement below method.
    abstract public function second_method();
  }
 
  class first_method
  {
    use first_trait;
   
    function second_method()
    {
      /* Code Here */
    }
  }

Note: trait can be composed from trait.

Conflicts in Trait

There can be a case, if any class using the more than one trait and two trait have same methods defined. In that case if you use two trait then it will give you Fatal Error.

But actually we can instruct the compiler for which method to use. This can be done using insteadof operator.

Let’s have an example for this:

trait first_trait { function first_function() { echo "From First Trait"; } } trait second_trait { function first_function() { echo "From Second Trait"; } } class first_class { use first_trait, second_trait { // This class will now call the method // first function from first_trait only first_trait::first_function insteadof second_trait; } } $obj = new first_class(); // Output: From First Trait $obj->first_function();
  trait first_trait
  {
    function first_function()
    {
      echo "From First Trait";
    }
  }

  trait second_trait
  {
    function first_function()
    {
      echo "From Second Trait";
    }
  }

  class first_class
  {
    use first_trait, second_trait
    {
      // This class will now call the method
      // first function from first_trait only
      first_trait::first_function insteadof second_trait;
    }
  }  
 
  $obj = new first_class();
  // Output: From First Trait
  $obj->first_function();

So now we have removed the confliction if the same function names. But what if you still want to use the methods of the both traits?

So in that case you can have as operator to the rescue. This operatoe is used for aliasing. Let’s see how it works:

trait first_trait { function first_function() { echo "From First Trait"; } } trait second_trait { function first_function() { echo "From Second Trait"; } } class first_class { use first_trait, second_trait { // This class will now call the method // first function from first_trait only first_trait::first_function insteadof second_trait; // first_function of second_traits can be // accessed with second_function second_trait::first_function as second_function; } } $obj = new first_class(); // Output: From First Trait $obj->first_function(); // Output: From Second Trait $obj->second_function();
  trait first_trait
  {
    function first_function()
    {
      echo "From First Trait";
    }
  }

  trait second_trait
  {
    function first_function()
    {
      echo "From Second Trait";
    }
  }

  class first_class
  {
    use first_trait, second_trait
    {
      // This class will now call the method
      // first function from first_trait only
      first_trait::first_function insteadof second_trait;
     
     
      // first_function of second_traits can be
      // accessed with second_function
      second_trait::first_function as second_function;
     
    }
  }  
 
  $obj = new first_class();
  // Output: From First Trait
  $obj->first_function();
 
  // Output: From Second Trait
  $obj->second_function();

Points to Keep in Mind About trait

  1. trait integrate into the precedence order of method overriding.
  2. trait can not be initialized with the keyword new same as class.
  3. trait can be composed from trait.
  4. We can use multiple trait in one class.
  5. trait supports all modifiers like final, static and abstract.
  6. We can use insteadof and as operators to resolve the conflicts in trait.

Coclusion

The main the major benefit of using the trait is code reusability and multiple inheritamce like functionality.

It would be great if you share your thought on trait about how you are plannig to use this upcoming feature and what are the other benefits of using the trait.

Note: PHP 5.4 is not stable yet, So you can visit this link to run the PHP code using 5.4 version.

Share This Article

  • YoTsumi

    How is managed the method overriding when a class uses 2 traits which implements the same function ?

    trait first_trait { function first_method() { echo "method1 A"; } } trait second_trait { function first_method() { echo "method1 B"; } } class first_class { use first_trait, second_trait; } $obj= new first_class(); $obj->first_method(); // Print : ???
    trait first_trait
      {
        function first_method() { echo "method1 A"; }
      }
     
      trait second_trait
      {
        function first_method() { echo "method1 B"; }
      }

      class first_class
      {
        use first_trait, second_trait;
      }
     
      $obj= new first_class();
      $obj->first_method(); // Print :  ???

    It’s one of the complexity of multiple inheritance.

    • http://www.xpertdeveloper.com Avinash

      Hi YoTsumi,

      It will give Fatal Error: Trait method first_method has not been applied, because there are collisions with other trait methods on first_class

      Please refer below link for code demo,

      http://codepad.viper-7.com/Gr65lj

    • http://www.xpertdeveloper.com Avinash

      Hi YoTsumi ,

      I have edited the post which describes your confusion about the multiple inheritance. So is that what you are looking for?

  • YoTsumi

    Thank you for that answer, it’s exactly what i was looking for.

    • http://www.xpertdeveloper.com Avinash

      Glad to Help :)

  • http://kinncj.com.br Kinn

    When the traits have the same property it’s done with a fatal error too.
    And you can’t apply and alias or insteadof at propertyes like you can do to methods… i think we got a bug ;)

    • http://www.xpertdeveloper.com Avinash

      @kinn:

      Yes seems to be like that… ;)

  • BASTA!

    I fail to see the point of the insteadof operator. The only information the interpreter really needs from us is which trait’s method to use, and that could be unambiguously specified by just naming that trait, without having to name all the other traits after the insteadof keyword.

  • Pingback: PHP Magic Constants Explained | Expert PHP Developer

  • Neeraj

    This is really a good post to understand what actually TRAIT is :)

  • Pingback: New Features in PHP 5.4 | Expert PHP Developer

  • Pingback: PHP review???:trait | Who's William?

  • vijay

    Nice Article Avinash

    Keep posting :)

  • I. Diot

    When reading about traits one really would like to flee to Java.

  • Pingback: Resoconto primo incontro | #pugMI

  • Satej

    Points to be kept in mind
    —-
    trait integrate into the precedence order of method overriding.

    By this do you mean to say that if the class using the trait already has a function contained in the trait, the class function will override the trait function?

    The tutorial/post was really helpful

  • Pingback: PHP 5.4 ? TRAIT ???????? | ??

  • Pingback: Trait in PHP 5.4 ← Bookmarks