← Back to PHP Course | Chapter 8: OOP | Lesson 9 of 14

PHP Traits

A trait is like a bundle of skills you can hand out to different classes, such as teaching swimming to both a dog and a duck. It lets classes share code without being related.
Syntax
php
trait TraitName {
    function method_name() { }
}

class ClassName {
    use TraitName;   // mix the methods in
}

What are Traits?

A trait is a reusable block of methods that can be mixed into multiple, otherwise unrelated classes using the use keyword, solving the problem of sharing code between classes that don't share a common parent.

Example: What are Traits?

php
<?php
// Define the trait `Greetable`, reusable methods to mix into a class
trait Greetable {
    // Define the function `greet` with no parameters
    function greet() {
        // Print "Hello!" to the output
        echo "Hello!";
    }
}
// Define the class `User`
class User {
    // Import `Greetable` into this file
    use Greetable;
}
// Create a new `User` instance, stored in `$user`
$user = new User();
$user->greet();
?>

Defining and Using Traits

Unlike inheritance, a trait doesn't establish an is-a relationship — it's purely a mechanism to copy in a set of method implementations, so a Loggable trait could be used by both a User class and an Order class with no relation to each other.

Example: Defining and Using Traits

php
<?php
// Define the trait `Loggable`, reusable methods to mix into a class
trait Loggable {
    // Define the function `log` taking `$msg`
    function log($msg) {
        // Print "[LOG] $msg\n" to the output
        echo "[LOG] $msg\n";
    }
}
// Define the class `User`
class User {
    // Import `Loggable` into this file
    use Loggable;
}
// Define the class `Order`
class Order {
    // Import `Loggable` into this file
    use Loggable;
}
(new User())->log("User created");
(new Order())->log("Order placed");
?>

Multiple Traits

A class can use multiple traits at once, and PHP has specific conflict-resolution rules (insteadof and as) for cases where two traits it uses happen to define a method with the same name.

Example: Multiple Traits

php
<?php
// Define the trait `A`, reusable methods to mix into a class
trait A {
    // Define the function `hello` with no parameters
    function hello() { echo "A"; }
}
// Define the trait `B`, reusable methods to mix into a class
trait B {
    // Define the function `hello` with no parameters
    function hello() { echo "B"; }
}
// Define the class `MyClass`
class MyClass {
    use A, B {
        A::hello insteadof B;
    }
}
(new MyClass())->hello();
?>

Conflict Resolution (insteadof)

Traits can define abstract methods too, requiring the class that uses them to supply an implementation, which lets a trait depend on behavior it expects the host class to provide.

Example: Conflict Resolution (insteadof)

php
<?php
// Define the trait `Shape`, reusable methods to mix into a class
trait Shape {
    // Define the function `area` with no parameters
    abstract function area();
    // Define the function `describe` with no parameters
    function describe() {
        // Print `"Area: " . $this->area()` to the output
        echo "Area: " . $this->area();
    }
}
// Define the class `Square`
class Square {
    // Import `Shape` into this file
    use Shape;
    // Define the function `area` with no parameters
    function area() {
        // Return `16` from this function
        return 16;
    }
}
(new Square())->describe();
?>

Trait Methods Visibility

Traits are a good fit for cross-cutting concerns like logging, timestamping, or serialization helpers that many otherwise-unrelated classes need, without forcing those classes into an artificial inheritance hierarchy.

Example: Trait Methods Visibility

php
<?php
// Define the trait `Timestampable`, reusable methods to mix into a class
trait Timestampable {
    // Define the function `timestamp` with no parameters
    function timestamp() {
        // Return `date("Y-m-d")` from this function
        return date("Y-m-d");
    }
}
// Define the class `Post`
class Post {
    // Import `Timestampable` into this file
    use Timestampable;
}
// Define the class `Comment`
class Comment {
    // Import `Timestampable` into this file
    use Timestampable;
}
// Print `(new Post())->timestamp()` to the output
echo (new Post())->timestamp();
?>
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Using two traits with the same method name and not resolving the conflict with insteadof.
  2. Trying to create an object from a trait directly, which is not possible.
  3. Expecting traits to work like inheritance, when they only copy their code into the class.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.