আগামী ৩০ নভেম্বর-২০১৭ তারিখ থেকে শুরু হচ্ছে পাঁচ মাস ব্যাপী Professional Web Design and Development with HTML, CSS PHP,MySQL,JavaScript, AJAX, JQUERY, Bootstrap and Live Project কোর্সের ৮৭ তম ব্যাচ এবং ২৪ নভেম্বর-২০১৭ তারিখ থেকে শুরু হচ্ছে চার মাস ব্যাপী Zend PHP-7 Certified PHP Engineering (Advance PHP) কোর্সের ৩৫ তম ব্যাচ। প্রত্যেকটি কোর্স এর ফী নির্ধারণ করা হয়েছে ৩০,০০০/= আগ্রহীদেরকে অতিসত্বর মাসুদ আলম স্যার এর সাথে যোগাযোগ করতে অনুরোধ করা যাচ্ছে। স্যার এর মোবাইল: 01722 81 75 91

Multiple Inheritance in PHP using Traits

[printfriendly]

Introduction

Trait is the new concept introduced in PHP 5.4. Which remove the limitation of the multiple inheritance in PHP. Before PHP 5.4, PHP support single inheritance and multiple interface but trait is going to remove the limitation of not having multiple inheritances. In This Tutorial, I’ll show a brief walkthrough of traits and  I’ll  show you how they can be used in real life situations.

What is trait?

According to php.net,

“Traits are a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies. The semantics of the combination of Traits and classes is defined in a way which reduces complexity, and avoids the typical problems associated with multiple inheritance and Mixins.

A Trait is similar to a class, but only intended to group functionality in a fine-grained and consistent way. It is not possible to instantiate a Trait on its own. It is an addition to traditional inheritance and enables horizontal composition of behavior; that is, the application of class members without requiring 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:

<?php
trait Foo
 {
 public function first_method() { echo "Hello"; /* Code Here */ }
 public function second_method() { echo "World"; /* Code Here */ }
 }
?>

Trait can be used within class using use keyword.

<?php
class Bar
 {
 // Using the Trait Here
 use Foo;

 }

 $obj = new Bar;

 // Executing the method from trait
 $obj->first_method(); //Hello
 $obj->second_method(); // World
?>

Traits can’t be instantiated so you can never do something like

<?php
$obj = new Foo;
?>

Without getting a big fatal error, but you can call it’s function statically.

<?php
Foo::first_method();
?>

It might show you a warning ‘Strict Standards: Non-static method Foo::first_method(); should not be called statically’, but you can make it a static function, and it will work without warnings.

Moving on, further exploring the powers of Traits

  

Precedence in traits

If same function found on multiple level(for example in child class, base class and trait) then there is some specific precedence order defined in php for choosing the function. For example

 <?php
 class Base{
 public public function sayHello(){
 echo "say hello from base";
 }
}

trait trt{
 public function sayHello()
 {
 echo "say hellow from trait";
 }
}

class Child extends Base{

use trt;

public function sayHello(){
 echo "hello from child class";
 }
}

$objCls = new Child;

$objCls->sayHello();

?>
 

Output:

hello from child class

Now in above code output will be “hello from child class”.Because precedence in the execution is like below list

  1. If method will be available in the main class(main_child in my example) then it will ignore everything and will use main class.
  2. If method is not available in main class and available in parent class and trait then it will choose from trait.

Using multiple traits

A class can use multiple traits. The following example demonstrates how to use multiple traits in the IDE class.

<?php

trait Subscriber{

public function subscriberLogin() {

echo "You\'re Logged in as Subscriber". '<br/>';

}

}

trait Contributor{

public function contributorLogin() {

echo "You're Logged in as Contributor". '<br/>';

}

}

trait Author{

public function AuthorLogin() {

echo "You're Logged in as Author." . '<br/>';

}

}

trait Administrator{

public function AdministratorLogin(){

echo "You're Logged in as Administrator" . '<br/>';

}

}

class Member{

use Subscriber, Contributor, Author, Administrator;

public function run() {

$this->subscriberLogin();

$this->contributorLogin();

$this->AuthorLogin();

$this->AdministratorLogin();

echo 'Members Login...done' . '<br/>';

}

}

$authentication = new Member();

$authentication->run();

?>

Output:

You’re Logged in as Subscriber

You’re Logged in as Contributor

You’re Logged in as Author.

You’re Logged in as Administrator

Members Login…done

Conflict Resolution in PHP Traits

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 insteadofoperator.

Let’s have an example for this:

 <?php

trait Foo

{

public function first_function()

{

echo "From Foo Trait";

}

}

trait Bar

{

public function first_function()

{

echo "From Bar Trait";

}

}

class FooBar

{

use Foo, Bar

{

// This class will now call the method

// first function from Foo only

Foo::first_function insteadof Bar;

}

}

$obj = new FooBar;

$obj->first_function();

?>
 

Output

From Foo Trait

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 operator is used for aliasing. Let’s see how it works:

<?php

trait Foo

{

public function first_function()

{

echo "From Foo Trait";

}

}

trait Bar

{

public function first_function()

{

echo "From Bar Trait";

}

}

class FooBar

{

use Foo, Bar

{

// This class will now call the method

// first function from Foo Trait only

Foo::first_function insteadof Bar;

// first_function of Bar can be

// accessed with second_function

Bar::first_function as second_function;

}

}

$obj = new FooBar;

// Output: From Foo Trait

$obj->first_function();

// Output: From Bar Trait

$obj->second_function();

?>

Changing Method Visibility 

As you have seen in my first example that I have used access modifier(public) in one of the function of traits. So whenever that trait will be used in any class the method  will be public. You can create trait’s method with modifier public, private, protected. Following is example of the access modifier.

<?php

trait visible{

public function pub(){

echo "this is public method";

}

private function priv(){

echo "this is private";

}

protected function proc(){

echo "echo this is protected function";

}

}

class cls{

use visible;

function callPriv(){

$this->priv();

}

}

$objCls = new cls();

$objCls->pub();//echo this is public method

//$objCls->priv();//Fatal error

$objCls->callPriv(); //this is private

?>

Now you can change access modifier of trait Methods using as keyword with following syntax.

<?php

trait visible{

public function pub(){

echo "this is public method";

}

private function priv(){

echo "this is private";

}

protected function proc(){

echo "echo this is protected function";

}

}

class cls{

use visible{

priv as public;

}

function callPriv(){

$this->priv();

}

}

$objCls = new cls();

$objCls->pub();//echo this is public method

//$objCls->priv();//This is private

$objCls->callPriv(); //this is private

?>

You can also modified the name of method of trait using as keyword.

<?php

trait visible{

public function pub(){

echo "this is public method";

}

private function priv(){

echo "this is private";

}

protected function proc(){

echo "echo this is protected function";

}

}

class cls{

use visible{

priv as public publ;

}

function callPriv(){

$this->publ();

}

}

$objCls = new cls();

$objCls->pub();//echo this is public method

//$objCls->publ();//This is private

$objCls->callPriv(); //this is private

?>

Traits Composed from Traits

A trait can be composed of other traits by using the use statement in the trait’s declaration. See the following example:

<?php

trait Hello

{

function sayHello() {

echo "Hello";

}

}

trait World

{

function sayWorld() {

echo "World";

}

}

trait HelloWorld

{

use Hello, World;

}

class MyWorld

{

use HelloWorld;

}

$world = new MyWorld();

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

?>

Traits and Properties

<?php

trait Calories {
public $banana = 105;
public $cake = 300;
public $donation = 205;
}

class Cookbook {
use Calories;
}

$c = new Cookbook;
printf($c->banana);</pre>
?>

Beware, you will not be able to define the same property in the Cookbook class. Meaning that if you do something like:

<?php
class Cookbook {
use Calories;
public $banana = 105; // if same value, this will result into a warning (E_STRICT)
public $banana = 106; // if different value, this will result into a fatal error
}
?>

So keep in mind, once you define properties in a trait you are not able to redefine them in the class.

Traits and Static methods and Properties

Traits can define both static members and static methods.

<?php

trait Calories {
public $banana = 105;
public $cake = 300;
public $donation = 205;
}

class Cookbook {
use Calories;
}

$c = new Cookbook;
printf($c->banana);</pre>
?>

Beware, you will not be able to define the same property in the Cookbook class. Meaning that if you do something like:

<?php
class Cookbook {
use Calories;
public $banana = 105; // if same value, this will result into a warning (E_STRICT)
public $banana = 106; // if different value, this will result into a fatal error
}
?>

Output:

Donate

Donate

2

Traits and Abstract members

Here’s how you can make a trait force you to implement a function.

<?php

trait Helper {
abstract public function greet();
}

class Foo {
use Helper;

public function greet($name){
printf('Hi there %s !', $name);
}
}

$foo = new Foo;

$foo->greet('Awesome Man');
?>

Output:

Hi there Awesome Man !

Practical example

Sorting a Array Using Trait

<?php
trait SortStrategy {
private $sort_field = null;
private function string_asc($item1, $item2) {
return strnatcmp($item1[$this->sort_field], $item2[$this->sort_field]);
}
private function string_desc($item1, $item2) {
return strnatcmp($item2[$this->sort_field], $item1[$this->sort_field]);
}
private function num_asc($item1, $item2) {
if ($item1[$this->sort_field] == $item2[$this->sort_field]) return 0;
return ($item1[$this->sort_field] < $item2[$this->sort_field] ? -1 : 1 );
}
private function num_desc($item1, $item2) {
if ($item1[$this->sort_field] == $item2[$this->sort_field]) return 0;
return ($item1[$this->sort_field] > $item2[$this->sort_field] ? -1 : 1 );
}
private function date_asc($item1, $item2) {
$date1 = intval(str_replace('-', '', $item1[$this->sort_field]));
$date2 = intval(str_replace('-', '', $item2[$this->sort_field]));
if ($date1 == $date2) return 0;
return ($date1 < $date2 ? -1 : 1 );
}
private function date_desc($item1, $item2) {
$date1 = intval(str_replace('-', '', $item1[$this->sort_field]));
$date2 = intval(str_replace('-', '', $item2[$this->sort_field]));
if ($date1 == $date2) return 0;
return ($date1 > $date2 ? -1 : 1 );
}
}

class Product {
public $data = array();

use SortStrategy;

public function get() {
// do something to get the data, for this ex. I just included an array
$this->data = array(
101222 => array('label' => 'Awesome product', 'price' => 10.50, 'date_added' => '2012-02-01'),
101232 => array('label' => 'Not so awesome product', 'price' => 5.20, 'date_added' => '2012-03-20'),
101241 => array('label' => 'Pretty neat product', 'price' => 9.65, 'date_added' => '2012-04-15'),
101256 => array('label' => 'Freakishly cool product', 'price' => 12.55, 'date_added' => '2012-01-11'),
101219 => array('label' => 'Meh product', 'price' => 3.69, 'date_added' => '2012-06-11'),
);
}

public function sort_by($by = 'price', $type = 'asc') {
if (!preg_match('/^(asc|desc)$/', $type)) $type = 'asc';
switch ($by) {
case 'name':
$this->sort_field = 'label';
uasort($this->data, array('Product', 'string_'.$type));
break;
case 'date':
$this->sort_field = 'date_added';
uasort($this->data, array('Product', 'date_'.$type));
break;
default:
$this->sort_field = 'price';
uasort($this->data, array('Product', 'num_'.$type));
}
}
}

$product = new Product();
$product->get();
$product->sort_by('date');
?>
<table border="1" width="100%">
<tr>
<th>SL</th>
<th>Label</th>
<th>Price</th>
<th>Date Added</th>
</tr>
<?php
 $i=1;
foreach($product->data as $value){
extract($value);
?>
<tr>
<td><?php echo $i++; ?></td>
<td><?php echo $label; ?></td>
<td><?php echo $price; ?></td>
<td><?php echo $date_added; ?></td>
</tr>
<?php
}
?>
</table>

Output:

Multiple Inheritance in PHP 5.4 using Traits

goodgood verygood 😀

Multiple Inheritance in PHP using Traits

Hi, My name is Masud Alam, love to work with Open Source Technologies, living in Dhaka, Bangladesh. I graduated in 2009 with a bachelor’s degree in Engineering from State University Of Bangladesh, I’m also a Certified Engineer on ZEND PHP 5.3, I served my first five years a number of leadership positions at Winux Soft Ltd, SSL Wireless Ltd, CIDA and MAX Group where I worked on ERP software and web development., but now i’m a co-founder and Chief Executive Officer and Managing Director of TechBeeo Software Consultancy Services Ltd. I’m also a Course Instructor of ZCPE PHP 7 Certification and professional web development course at w3programmers Training Institute – a leading Training Institute in the country.

4 comments on “Multiple Inheritance in PHP using Traits
  1. That’s awesome article about PHP Traits and Thank you very much Sir.

    I got one error : Fatal error: Multiple access type modifiers are not allowed in ……

    # it’s may be type mistake.

    class Base{

    public public function sayHello(){
    //remove please one public keyword
    echo “say hello from base”;

    }

    }

Leave a Reply

Your email address will not be published. Required fields are marked *