PHPのトレイト(Trait)は、複数のクラスでコード(メソッドやプロパティ)を共有するための仕組みです。PHPは単一継承しかサポートしないため、継承では解決できないコードの再利用問題を、トレイトで解決できます。
trait で定義し、使いたいクラスで use キーワードで取り込みます。1つのクラスが複数のトレイトを使え、まるでコードを「コピー&ペースト」するように機能を追加できます。
基本的な使い方
PHP
<?php
trait Timestampable {
private string $createdAt;
private string $updatedAt;
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 getTimestamps(): string {
return "作成: {$this->createdAt}、更新: {$this->updatedAt}";
}
}
class User {
use Timestampable;
public function __construct(public string $name) {
$this->setCreatedAt();
$this->setUpdatedAt();
}
}
class Article {
use Timestampable;
public function __construct(public string $title) {
$this->setCreatedAt();
$this->setUpdatedAt();
}
}
$user = new User("田中");
echo "ユーザー: {$user->name} - {$user->getTimestamps()}\n";
$article = new Article("PHP入門");
echo "記事: {$article->title} - {$article->getTimestamps()}\n";
実行結果
ユーザー: 田中 - 作成: 2026-02-19 10:00:00、更新: 2026-02-19 10:00:00
記事: PHP入門 - 作成: 2026-02-19 10:00:00、更新: 2026-02-19 10:00:00
Timestampable トレイトを User と Article の両方で使っています。継承関係がないクラス間でも同じ機能を共有できます。
複数のトレイトを使う
PHP
<?php
trait HasName {
private string $name;
public function getName(): string { return $this->name; }
public function setName(string $name): void { $this->name = $name; }
}
trait HasEmail {
private string $email;
public function getEmail(): string { return $this->email; }
public function setEmail(string $email): void { $this->email = $email; }
}
trait Loggable {
public function log(string $action): void {
echo "[LOG] " . get_class($this) . ": {$action}\n";
}
}
class Employee {
use HasName, HasEmail, Loggable;
public function __construct(string $name, string $email) {
$this->setName($name);
$this->setEmail($email);
$this->log("新規作成");
}
public function show(): void {
echo "{$this->getName()} ({$this->getEmail()})\n";
}
}
$emp = new Employee("田中太郎", "tanaka@example.com");
$emp->show();
実行結果
[LOG] Employee: 新規作成
田中太郎 (tanaka@example.com)
メソッド名の衝突解決
複数のトレイトに同名のメソッドがある場合、insteadof と as で衝突を解決します。
PHP
<?php
trait Japanese {
public function greet(): string {
return "こんにちは";
}
}
trait English {
public function greet(): string {
return "Hello";
}
}
class Bilingual {
use Japanese, English {
Japanese::greet insteadof English; // Japaneseを優先
English::greet as greetInEnglish; // Englishは別名で使う
}
}
$person = new Bilingual();
echo $person->greet() . "\n";
echo $person->greetInEnglish() . "\n";
実行結果
こんにちは
Hello
実用的な例
PHP
<?php
trait SoftDelete {
private bool $deleted = false;
private ?string $deletedAt = null;
public function softDelete(): void {
$this->deleted = true;
$this->deletedAt = date("Y-m-d H:i:s");
}
public function restore(): void {
$this->deleted = false;
$this->deletedAt = null;
}
public function isDeleted(): bool {
return $this->deleted;
}
}
class Post {
use SoftDelete;
public function __construct(public string $title) {}
public function getStatus(): string {
$status = $this->isDeleted() ? "削除済み" : "公開中";
return "{$this->title}({$status})";
}
}
$post = new Post("PHPトレイト解説");
echo $post->getStatus() . "\n";
$post->softDelete();
echo $post->getStatus() . "\n";
$post->restore();
echo $post->getStatus() . "\n";
実行結果
PHPトレイト解説(公開中)
PHPトレイト解説(削除済み)
PHPトレイト解説(公開中)
ポイント
トレイトはLaravelなどのフレームワークで広く使われています。例えば、SoftDeletes(論理削除)、HasFactory(テストデータ生成)、Notifiable(通知送信)などがトレイトとして提供されています。
注意
トレイトを多用しすぎると、クラスの責務が不明確になりやすいです。「このクラスは何をするのか」が分かりにくくならないよう、1つのトレイトには1つの明確な責務を持たせましょう。
まとめ
traitでコードの断片を定義し、useでクラスに取り込める- 継承関係のない複数のクラスでコードを共有できる
- 1つのクラスで複数のトレイトを同時に使える
- メソッド名の衝突は
insteadofとasで解決する - 論理削除やタイムスタンプなど、横断的な機能に最適