Reader Stacks

What Are Traits in PHP? A Practical Example

Traits let you share a set of methods across multiple classes that can't share a common parent — a form of horizontal code reuse PHP added specifically because single inheritance wasn't enough.

What Are Traits in PHP? A Practical Example

Traits are PHP's mechanism for sharing a set of methods across multiple, otherwise-unrelated classes — a form of horizontal code reuse that exists specifically because PHP only supports single inheritance, and some shared behavior doesn't fit neatly into one class hierarchy.

The problem traits solve

If both a User model and a Post model need the same "soft delete" behavior, but they don't (and shouldn't) share a common parent class beyond Model itself, inheritance alone can't cleanly share that behavior between them — a trait can be mixed into both independently.

Defining a trait

trait Loggable
{
    public function logActivity(string $message): void
    {
        Log::info(get_class($this) . ": {$message}", ['id' => $this->id]);
    }
}

Using it in a class

class Order
{
    use Loggable;

    public function markAsShipped()
    {
        $this->status = 'shipped';
        $this->save();
        $this->logActivity('Order marked as shipped');
    }
}

class User
{
    use Loggable;

    public function suspend()
    {
        $this->suspended = true;
        $this->save();
        $this->logActivity('User account suspended');
    }
}

Order and User share no inheritance relationship, but both now have a working logActivity() method through the same trait.

Using multiple traits in one class

class Post
{
    use Loggable, HasSlug, Searchable;
}

A class can use as many traits as needed — this is exactly how Eloquent models often compose several independent behaviors (soft deletes, factories, notifications) without a deep, rigid inheritance chain.

Trait constructors: bootHasSlug and similar conventions

PHP traits don't have their own real constructor, but Laravel's Eloquent uses a naming convention (bootTraitName, initializeTraitName) that it calls automatically for any trait following that pattern — this is a framework-level convention built on top of plain PHP traits, not a native PHP feature.

Resolving a method name conflict between two traits

class Report
{
    use Exportable, Printable {
        Exportable::export insteadof Printable;
        Printable::export as printExport;
    }
}

If two traits used in the same class define a method with the same name, PHP requires resolving the conflict explicitly with insteadof (choosing one) and optionally as (aliasing the other under a different name) — without this, using both traits together is a fatal error.

When to reach for a trait vs. a service class or composition

A trait suits small, focused, genuinely reusable behavior shared across otherwise-unrelated classes — for anything with real internal state, more complex dependencies, or behavior that would benefit from being independently testable and swappable, a proper service class injected via composition is generally the better-designed choice.