ZetCode

PHP Traits

last modified April 16, 2025

PHP traits are a mechanism for code reuse in single inheritance languages. They enable developers to reuse sets of methods freely in several classes. Traits reduce the limitations of single inheritance by allowing horizontal composition of behavior.

Basic Definitions

A trait is similar to a class but intended to group functionality in a fine-grained way. Traits cannot be instantiated on their own. They are included in classes using the use keyword.

Traits solve the multiple inheritance problem by allowing method reuse. All trait methods become available in the class that uses the trait. Traits can define both properties and methods.

Syntax: trait TraitName { methods and properties } and class ClassName { use TraitName; }. Traits support abstract methods and can use other traits.

Basic Trait Usage

This example demonstrates a simple trait with one method being used in a class.

basic_trait.php
<?php

declare(strict_types=1);

trait Greeting {
    public function sayHello() {
        echo "Hello from trait!";
    }
}

class MyClass {
    use Greeting;
}

$obj = new MyClass();
$obj->sayHello();

The Greeting trait defines a sayHello method. MyClass uses the trait and gains access to its method. The method is called on an instance of the class. Traits provide a way to share methods between unrelated classes.

Multiple Traits

This example shows how a class can use multiple traits simultaneously.

multiple_traits.php
<?php

declare(strict_types=1);

trait Logger {
    public function log(string $message) {
        echo "Logging: $message";
    }
}

trait Debugger {
    public function debug(string $message) {
        echo "Debugging: $message";
    }
}

class Application {
    use Logger, Debugger;
}

$app = new Application();
$app->log("User logged in");
$app->debug("Variable not set");

The class Application uses both Logger and Debugger traits. It can call methods from both traits. Multiple traits are separated by commas in the use statement. This demonstrates horizontal composition of behavior.

Trait Conflict Resolution

This example demonstrates resolving method name conflicts between traits.

trait_conflict.php
<?php

declare(strict_types=1);

trait A {
    public function smallTalk() {
        echo "a";
    }
}

trait B {
    public function smallTalk() {
        echo "b";
    }
}

class Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::smallTalk as aTalk;
    }
}

$talker = new Talker();
$talker->smallTalk(); // Outputs "b"
$talker->aTalk();     // Outputs "a"

Both traits define a smallTalk method causing a conflict. The insteadof operator specifies which trait's method to use. The as operator creates an alias for the excluded method. This allows access to both implementations under different names.

Trait Properties

This example shows how traits can define properties used by classes.

trait_properties.php
<?php

declare(strict_types=1);

trait Counter {
    private int $count = 0;

    public function increment() {
        $this->count++;
    }

    public function getCount(): int {
        return $this->count;
    }
}

class Clicker {
    use Counter;
}

$clicker = new Clicker();
$clicker->increment();
$clicker->increment();
echo $clicker->getCount(); // Outputs 2

The Counter trait defines a private property and methods to manipulate it. The Clicker class uses the trait and gains access to both the property and methods. Traits can maintain state through properties just like classes.

Abstract Methods in Traits

This example demonstrates using abstract methods in traits that must be implemented by the using class.

abstract_trait.php
<?php

declare(strict_types=1);

trait Renderable {
    abstract public function getData(): array;

    public function render() {
        $data = $this->getData();
        echo "Rendering: " . implode(', ', $data);
    }
}

class Product {
    use Renderable;

    public function getData(): array {
        return ['Name', 'Price', 'Description'];
    }
}

$product = new Product();
$product->render();

The Renderable trait defines an abstract getData method. Any class using the trait must implement this method. The trait's render method relies on this implementation. This creates a contract between trait and class.

Trait Composition

This example shows how traits can use other traits, enabling composition.

trait_composition.php
<?php

declare(strict_types=1);

trait Hello {
    public function sayHello() {
        echo "Hello ";
    }
}

trait World {
    public function sayWorld() {
        echo "World";
    }
}

trait HelloWorld {
    use Hello, World;

    public function sayHelloWorld() {
        $this->sayHello();
        $this->sayWorld();
    }
}

class MyHelloWorld {
    use HelloWorld;
}

$obj = new MyHelloWorld();
$obj->sayHelloWorld(); // Outputs "Hello World"

The HelloWorld trait uses both Hello and World traits. MyHelloWorld class then uses the composed trait. Traits can be nested to build complex behavior from simpler components. This promotes code reuse and modularity.

Changing Method Visibility

This example demonstrates changing method visibility when using traits.

trait_visibility.php
<?php

declare(strict_types=1);

trait Message {
    private function secretMessage() {
        echo "This is secret!";
    }

    public function publicMessage() {
        echo "This is public!";
    }
}

class Messenger {
    use Message {
        secretMessage as public revealedMessage;
        publicMessage as private hiddenMessage;
    }
}

$messenger = new Messenger();
$messenger->revealedMessage(); // Now public
// $messenger->hiddenMessage(); // Would cause error (private)

The trait's secretMessage is made public with a new name. The publicMessage is made private under a new name. This allows adjusting method visibility when using traits. The original trait methods remain unchanged in their visibility.

Best Practices

Source

PHP Traits Documentation

This tutorial covered PHP traits with practical examples showing how to reuse code across classes and resolve trait conflicts effectively.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all PHP basics tutorials.