SyntaxStudy
Sign Up
PHP Intermediate 8 min read

Traits Basics

Traits are a mechanism for code reuse in PHP's single-inheritance model. A trait is like a class, but cannot be instantiated — it is designed to be used inside classes with the use keyword.

  • Traits can contain methods and properties.
  • A class can use multiple traits.
  • Traits can use other traits.

Common use-cases: logging, timestamps, soft-delete, auditing.

Example
<?php
trait Timestampable
{
    private ?string $createdAt = null;
    private ?string $updatedAt = null;

    public function setCreatedAt(): void
    {
        $this->createdAt = date('Y-m-d H:i:s');
    }

    public function setUpdatedAt(): void
    {
        $this->updatedAt = date('Y-m-d H:i:s');
    }

    public function getCreatedAt(): ?string { return $this->createdAt; }
    public function getUpdatedAt(): ?string { return $this->updatedAt; }
}

trait SoftDeletable
{
    private ?string $deletedAt = null;

    public function softDelete(): void
    {
        $this->deletedAt = date('Y-m-d H:i:s');
    }

    public function restore(): void
    {
        $this->deletedAt = null;
    }

    public function isDeleted(): bool
    {
        return $this->deletedAt !== null;
    }
}

class Post
{
    use Timestampable, SoftDeletable; // use multiple traits

    public function __construct(public string $title)
    {
        $this->setCreatedAt();
    }

    public function update(string $title): void
    {
        $this->title = $title;
        $this->setUpdatedAt();
    }
}

$post = new Post('Hello World');
echo $post->getCreatedAt();  // 2024-07-15 14:00:00
$post->update('Hello PHP');
echo $post->getUpdatedAt();  // 2024-07-15 14:00:01

$post->softDelete();
echo $post->isDeleted() ? 'deleted' : 'active'; // deleted
$post->restore();
echo $post->isDeleted() ? 'deleted' : 'active'; // active
Pro Tip

Tip: Traits are best for small, focused, reusable behaviours — not a dumping ground for miscellaneous methods. If a trait grows large or starts depending on many external methods, consider refactoring it into a dedicated class that is injected as a dependency.