Traits in PHP — An enhanced feature of inheritance

ZappyTalks
4 min readNov 3, 2019

OOPs is buzzword and powerful concept in programming or software development that provides re-usablity and better management of code. Inheritance is one of the feature of OOPs concept that enhances re-usability of code. We can achieve inheritance by inheriting a class from another class that is called single inheritance.

<?php
class Foo {

}

class Bar extends Foo {

}

?>

What is traits?

Traits has been introduced in PHP 5.4 version as a new feature and is is extensively being used. A trait is a collection of methods that cannot be instantiated like an abstract class, can be used with a class. The exact definition of trait as below which is mentioned in PHP documentation.

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 behaviour; that is, the application of class members without requiring inheritance.

Why do we use traits?

Suppose, there are some methods in different class and want to use that classes to prevent code duplication but PHP cannot support multiple inheritance. To overcome the problem of multiple inheritance trait can be used.

How to use traits?

Declaring a trait is similar to declaring a new class but using trait keyword as shown in the below example:

<?php
trait Logger {
function log($msg) {
echo date('Y-m-d h:i:s') .' '. $msg;
}
}

?>

To use trait in a class, you need to use “use” keyword. All trait’s methods are automatically available in the class where it is being used. Let’s see following example to know how to use trait Logger in class User.

<?php
class User {
use Logger;

public function saveUser()
{
$this->log("User saved")
}
}

?>

Trait’s method can be called as below too, you can use these methods as per your requirement:

<?php
class User {
use Logger;

public function saveUser()
{

}
}

$u = new User();
$u->saveUser();
$u->log("User saved");

?>

How to use multiple traits?

A class can use multiple traits. The following example demonstrates how to use multiple traits in a class. The following example simulates life cycle of java code execution.

<?php

trait JavaSourceCode{
function write() {
echo 'Writing Program<br>';
}
}
trait JavaCompiler{
function compile() {
echo 'Generating Byte code<br>';
}
}

trait JavaVirtualMachine{
function execute() {
echo 'Executing Byte code<br>';
}
}


class JavaCodeLifeCycle{
use JavaSourceCode, JavaCompiler, JavaVirtualMachine;

function runProgram() {
$this->write();
$this->compile();
$this->execute();

echo 'done...';
}
}

$javaCode = new JavaCodeLifeCycle();
$javaCode->runProgram();

?>

Composing multiple traits

We can compose multiple traits, means traits can be used within another trait. See the following example to understand:

<?php
trait FileRead{
public function read($from){
echo $from;
}
}

trait FileWrite{
public function write($to){
echo $to;
}
}

trait FileCut{
use FileRead, FileWrite;
public function cut($from, $to){
$this->read($from);
$this->write($to);
}
}

class FileOperation{
use FileCut;
public function moveFile($from, $to){
$this->cut($from, $to);
}
}

?>

Firstly, created FileRead and FileWrite traits then use them in FileCut. FileCut trait is being used in class FileOperation.

Overriding trait’s methods and resolve confliction

When use multiple traits that have same method name in a class, PHP will raise error. But we can direct PHP using “insteadof” keyword which trait to be used in that class. Let’s see following example:

<?php
trait Java{
public function run($statements){
echo 'Execute ' . $statements . '<br/>';
}
}

trait Python{
public function run($statements){
echo 'Execute ' . $statements . '<br/>';
}
}

class Program{
use Java, Python{
Java::run insteadof Python;
}
}

$runner = new Program();
$runner->run('Statements');
?>

Here, we resolved the confliction between methods of both traits by specifying use run() method of Java trait instead of Python.

But we are unable to use run() method of Python trait. So here a question is raised that how can we use methods of both trait?

Yes, we can do it by using aliases for the same method name of multiple traits within the class. Let’s do some changes in above example.

<?php
trait Java{
public function run($statements){
echo 'Execute ' . $statements . '<br/>';
}
}

trait Python{
public function run($statements){
echo 'Execute ' . $statements . '<br/>';
}
}

class Program{
use Java, Python{
Python::run as runPython;
Java::run insteadof Python;
}
}

$runner = new Program();
$runner->run('Java Statements');
$runner->runPython('Python Statements');
?>

The method run() of the Python trait has a new name runPython in the context of the Program class.

Hope you like this and enjoy coding.

If you have any questions or suggestions, let me know!

--

--

ZappyTalks
0 Followers

Let’s simplify and feel either informed or inspired