Menu
Coddy logo textTech

Using Multiple Traits

Part of the Object Oriented Programming section of Coddy's PHP journey — lesson 52 of 91.

A single trait is useful, but the real power comes when you combine multiple traits in one class. PHP lets you include as many traits as you need, giving your class capabilities from several sources at once.

To use multiple traits, simply list them separated by commas after the use keyword:

<?php
trait Timestampable {
    public function getTimestamp(): string {
        return date('Y-m-d H:i:s');
    }
}

trait Identifiable {
    private string $id;
    
    public function generateId(): void {
        $this->id = uniqid('id_');
    }
    
    public function getId(): string {
        return $this->id;
    }
}

class Post {
    use Timestampable, Identifiable;
    
    public function __construct(public string $title) {
        $this->generateId();
    }
}

$post = new Post("Hello World");
echo $post->getId() . " - " . $post->getTimestamp();

Output:

id_6789abc123 - 2024-01-15 10:30:00

The Post class now has methods from both traits. Each trait contributes its own functionality - Timestampable provides time-related methods while Identifiable handles unique IDs. This approach keeps each trait focused on a single responsibility, making your code more modular and reusable.

What happens when two traits have methods with the same name? That's a conflict situation we'll explore in the next lesson.

challenge icon

Challenge

Easy

Let's build a product management system that combines multiple traits to give products both pricing and inventory capabilities. Each trait will handle a single responsibility, and your product class will gain functionality from both.

You'll organize your code across three files:

  • Priceable.php — Create a trait called Priceable that handles pricing functionality. The trait should have:
    • A private property $price (float)
    • A method setPrice(float $price) that stores the price
    • A method getPrice() that returns the price
    • A method getFormattedPrice() that returns the price formatted as "$[price]" with 2 decimal places
  • Stockable.php — Create a trait called Stockable that manages inventory. The trait should have:
    • A private property $stock (integer)
    • A method setStock(int $quantity) that stores the stock quantity
    • A method getStock() that returns the current stock
    • A method isInStock() that returns true if stock is greater than 0, false otherwise
  • main.php — Include both trait files and create a Product class that uses both Priceable and Stockable traits. Use constructor promotion to define a public $name property. The constructor should also accept a price and stock quantity, using the trait methods to set them.

    You'll receive three inputs: a product name, a price, and a stock quantity. Create a product with these values and print four lines:

    • The product name
    • The formatted price (using getFormattedPrice())
    • The stock quantity
    • "Available" if in stock, or "Out of stock" if not

This demonstrates how multiple traits work together — your Product class gains pricing capabilities from one trait and inventory management from another, keeping each concern neatly separated while combining them into a fully-featured product.

Cheat sheet

To use multiple traits in a class, list them separated by commas after the use keyword:

<?php
trait Timestampable {
    public function getTimestamp(): string {
        return date('Y-m-d H:i:s');
    }
}

trait Identifiable {
    private string $id;
    
    public function generateId(): void {
        $this->id = uniqid('id_');
    }
    
    public function getId(): string {
        return $this->id;
    }
}

class Post {
    use Timestampable, Identifiable;
    
    public function __construct(public string $title) {
        $this->generateId();
    }
}

$post = new Post("Hello World");
echo $post->getId() . " - " . $post->getTimestamp();
// Output: id_6789abc123 - 2024-01-15 10:30:00

Each trait contributes its own functionality to the class. This approach keeps each trait focused on a single responsibility, making code more modular and reusable.

Try it yourself

<?php
require_once 'Priceable.php';
require_once 'Stockable.php';

// TODO: Create a Product class that uses both Priceable and Stockable traits
// Use constructor promotion for the public $name property
// The constructor should accept name, price, and stock, and use trait methods to set price and stock

class Product {
    // TODO: Use the traits here

    // TODO: Implement constructor with constructor promotion for $name
    // and set price and stock using trait methods
}

// Read input
$name = trim(fgets(STDIN));
$price = floatval(trim(fgets(STDIN)));
$stock = intval(trim(fgets(STDIN)));

// TODO: Create a Product instance with the input values

// TODO: Print the product name
// TODO: Print the formatted price using getFormattedPrice()
// TODO: Print the stock quantity
// TODO: Print "Available" if in stock, or "Out of stock" if not
?>
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming