PHP Traits
In this page:
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
// 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();
?>
Login to try C/C++/Java/PHP code in the editor
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
// 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");
?>
Login to try C/C++/Java/PHP code in the editor
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
// 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();
?>
Login to try C/C++/Java/PHP code in the editor
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
// 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();
?>
Login to try C/C++/Java/PHP code in the editor
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
// 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();
?>
Login to try C/C++/Java/PHP code in the editor
- Using two traits with the same method name and not resolving the conflict with
insteadof. - Trying to create an object from a trait directly, which is not possible.
- Expecting traits to work like inheritance, when they only copy their code into the class.
Chapter Quiz — Complete all 14 topics to unlock
0/14 topics done
Complete these topics first: