PHP Traits

Reusing code across multiple classes

🔧 What are PHP Traits?

Traits are a mechanism for code reuse in PHP. They allow you to share methods across multiple classes without using inheritance, solving the single inheritance limitation in PHP.


<?php
// Simple trait example
trait Greetings {
    public function sayHello() {
        return "Hello!";
    }
}

class User {
    use Greetings;
}

$user = new User();
echo $user->sayHello(); // Hello!
?>
                                    

Why Use Traits?

♻️

Code Reuse

Share methods across unrelated classes

DRY Principle Efficiency
🎯

No Inheritance

Avoid complex inheritance hierarchies

Flexible Simple
🔀

Multiple Traits

Use multiple traits in one class

Composable Modular
🧩

Horizontal Reuse

Share functionality across class trees

Cross-cutting Versatile

🔹 Basic Trait Example

Traits are declared using the trait keyword and included in classes using the use keyword. They provide a simple way to share methods between classes.

<?php
// Define a trait
trait Timestamp {
    public function getTimestamp() {
        return date('Y-m-d H:i:s');
    }
}

// Use trait in a class
class Article {
    use Timestamp;
    
    public $title = "My Article";
}

class Comment {
    use Timestamp;
    
    public $text = "Great post!";
}

$article = new Article();
$comment = new Comment();

echo "Article: " . $article->getTimestamp() . "<br>";
echo "Comment: " . $comment->getTimestamp();
?>

Output:

Article: 2025-10-14 10:30:45

Comment: 2025-10-14 10:30:45

🔹 Using Multiple Traits

A class can use multiple traits by separating them with commas, combining functionality from different sources into a single class.

<?php
trait Logger {
    public function log($message) {
        return "LOG: $message";
    }
}

trait Validator {
    public function validate($data) {
        return !empty($data);
    }
}

class User {
    use Logger, Validator;
    
    public $name;
    
    public function create($name) {
        if ($this->validate($name)) {
            $this->name = $name;
            return $this->log("User $name created");
        }
        return "Invalid data";
    }
}

$user = new User();
echo $user->create("John");
?>

Output:

LOG: User John created

🔹 Trait Method Conflicts

When two traits have methods with the same name, you can resolve conflicts using the insteadof and as operators to specify which method to use.

<?php
trait English {
    public function greet() {
        return "Hello";
    }
}

trait Spanish {
    public function greet() {
        return "Hola";
    }
}

class Person {
    use English, Spanish {
        English::greet insteadof Spanish;
        Spanish::greet as greetSpanish;
    }
}

$person = new Person();
echo $person->greet() . "<br>";
echo $person->greetSpanish();
?>

Output:

Hello

Hola

🔹 Changing Method Visibility

You can change the visibility of trait methods when using them in a class, making public methods private or vice versa as needed.

<?php
trait Helper {
    public function publicMethod() {
        return "This is public";
    }
    
    private function privateMethod() {
        return "This is private";
    }
}

class MyClass {
    use Helper {
        publicMethod as private;
        privateMethod as public makePublic;
    }
    
    public function test() {
        return $this->publicMethod();
    }
}

$obj = new MyClass();
echo $obj->test() . "<br>";
echo $obj->makePublic();
?>

Output:

This is public

This is private

🔹 Traits with Properties

Traits can contain properties as well as methods, allowing you to share both data and behavior across multiple classes.

<?php
trait Counter {
    public $count = 0;
    
    public function increment() {
        $this->count++;
        return $this->count;
    }
    
    public function getCount() {
        return $this->count;
    }
}

class PageView {
    use Counter;
}

class ClickTracker {
    use Counter;
}

$page = new PageView();
$page->increment();
$page->increment();

$clicks = new ClickTracker();
$clicks->increment();

echo "Page views: " . $page->getCount() . "<br>";
echo "Clicks: " . $clicks->getCount();
?>

Output:

Page views: 2

Clicks: 1

🔹 Traits Composed of Traits

Traits can use other traits, allowing you to build complex functionality by composing simpler traits together in a hierarchical structure.

<?php
trait Name {
    public $name;
    
    public function setName($name) {
        $this->name = $name;
    }
}

trait Email {
    public $email;
    
    public function setEmail($email) {
        $this->email = $email;
    }
}

trait UserInfo {
    use Name, Email;
    
    public function getInfo() {
        return "Name: {$this->name}, Email: {$this->email}";
    }
}

class Account {
    use UserInfo;
}

$account = new Account();
$account->setName("Alice");
$account->setEmail("[email protected]");
echo $account->getInfo();
?>

Output:

Name: Alice, Email: [email protected]

🔹 Abstract Methods in Traits

Traits can declare abstract methods that must be implemented by the class using the trait, ensuring required functionality is provided.

<?php
trait Formatter {
    abstract public function getData();
    
    public function format() {
        $data = $this->getData();
        return strtoupper($data);
    }
}

class Product {
    use Formatter;
    
    private $name = "laptop";
    
    public function getData() {
        return $this->name;
    }
}

$product = new Product();
echo $product->format();
?>

Output:

LAPTOP

💡 Key Points to Remember:

  • Traits enable horizontal code reuse without inheritance
  • Use the trait keyword to define traits
  • Use the use keyword to include traits in classes
  • A class can use multiple traits
  • Resolve method conflicts with insteadof and as
  • Traits can contain properties, methods, and abstract methods
  • Traits can use other traits
  • Method visibility can be changed when using traits

🧠 Test Your Knowledge

What keyword is used to include a trait in a class?