PHPのtrait
が実務で初めて遭遇したときに、こんな便利な書き方があるのかと感動したので忘備録として記事にします。
traitとは
PHPのtraitとは、クラスのコードを再利用するための仕組みのことを指します。
簡単に説明すると、継承の代わりに一部のメソッドやプロパティだけを他のクラスに取り込むことができます。
traitの使い方(サンプルコード)
traitの使い方は以下の通り。
<?php
trait HelloTrait {
public function sayHello() {
echo "Hello!";
}
}
trait WorldTrait {
public function sayWorld() {
echo "World!";
}
}
class MyClass {
use HelloTrait, WorldTrait;
}
$obj = new MyClass();
$obj->sayHello(); // => Hello!
$obj->sayWorld(); // => World!
同じメソッドが衝突する場合は、以下のように書きます。
trait A {
public function hello() {
echo "Hello from A";
}
}
trait B {
public function hello() {
echo "Hello from B";
}
}
class MyClass {
use A, B {
A::hello insteadof B; // Aのhelloを優先
B::hello as helloFromB; // Bのhelloに別名をつける
}
}
$obj = new MyClass();
$obj->hello(); // => Hello from A
$obj->helloFromB(); // => Hello from B
traitのメリット
- 同じ処理(ロジック)を複数のクラスで共通して使いたいときに、毎回書く必要がない
- 継承だと1つの親クラスしか継承できないが、traitは複数組み合わせて使える
- traitなら実装済みのメソッドを「そのまま使える」ので、手軽
- trait側を修正するだけで使っているクラス全部に反映される
traitのデメリット
- どのクラスでどのtraitが使われているか把握しにくくなる
- メソッド名が重複したときの挙動がわかりにくい
- 継承とtraitの関係が複雑になると、設計がごっちゃになる
以上がtraitの説明とサンプルコードになります。
おまけ
1年前の日時を返すtraitのサンプルコードも載せておきます。
ぜひ参考にしてみてください。
<?php
trait OneYearFilter
{
/**
* 1年前の日時を返す
*
* @return string
*/
public function getOneYearAgo()
{
return date('Y-m-d H:i:s', strtotime('-1 year'));
}
}
class User
{
use OneYearFilter;
public function getWhereCreatedAfterOneYearAgo()
{
$oneYearAgo = $this->getOneYearAgo();
return "WHERE created_at >= '{$oneYearAgo}'";
}
}