Skip to content

PHP Tutorial Advanced OOP

Traits

Lesson 215 of 369 2 min read By Deepak Paswan Updated Oct 5, 2026

A PHP class can extend only one parent. A trait is a way to share code between classes that are not related by inheritance. Think of it as copy-and-paste handled by PHP.

index.php
PHP
<?php
trait Timestamps
{
    public ?string $createdAt = null;

    public function touch(string $time): void
    {
        $this->createdAt = $time;
    }
}

class Post
{
    use Timestamps;
}

class Comment
{
    use Timestamps;
}

$post = new Post();
$post->touch("2026-01-01");

echo $post->createdAt;
Output
OUTPUT
2026-01-01

Both Post and Comment got $createdAt and touch() from the trait, though they have no common parent.

Several traits

index.php
PHP
<?php
trait Hello
{
    public function hello(): string { return "Hello"; }
}

trait World
{
    public function world(): string { return "World"; }
}

class Greeter
{
    use Hello, World;

    public function greet(): string
    {
        return $this->hello() . " " . $this->world();
    }
}

echo (new Greeter())->greet();
Output
OUTPUT
Hello World

Conflicts

If two traits have a method with the same name, PHP raises a fatal error unless you choose.

index.php
PHP
<?php
trait A
{
    public function say(): string { return "A"; }
}

trait B
{
    public function say(): string { return "B"; }
}

class Talker
{
    use A, B {
        A::say insteadof B;      // use A's version
        B::say as sayFromB;      // keep B's under another name
    }
}

$t = new Talker();

echo $t->say() . $t->sayFromB();
Output
OUTPUT
AB

Abstract and static members in traits

A trait can demand that the class provides something.

index.php
PHP
<?php
trait Describable
{
    abstract public function name(): string;

    public function describe(): string
    {
        return "This is " . $this->name();
    }
}

class Book
{
    use Describable;

    public function name(): string
    {
        return "a book";
    }
}

echo (new Book())->describe();
Output
OUTPUT
This is a book

A common use: a logging helper

index.php
PHP
<?php
trait Logs
{
    private array $log = [];

    protected function log(string $message): void
    {
        $this->log[] = $message;
    }

    public function logs(): array
    {
        return $this->log;
    }
}

class Importer
{
    use Logs;

    public function run(): void
    {
        $this->log("Started");
        $this->log("Finished");
    }
}

$i = new Importer();
$i->run();

echo implode(", ", $i->logs());
Output
OUTPUT
Started, Finished

Limits of traits

  • A trait is not a type. You cannot write a parameter type of a trait, and instanceof does not work with it. Use an interface for that.
  • Overusing traits makes it hard to see where a method comes from.
  • Traits can hide a design problem. If a trait grows large, it is probably a class.

Traits plus interfaces

A good pattern is to define an interface for the type, and a trait that gives a ready implementation.

info
Why this matters in Laravel
Laravel uses traits everywhere: HasFactory, Notifiable, SoftDeletes. Adding use SoftDeletes; to a model gives it a whole set of methods. Now you know what that line does.