PHP 5.4 引入 Traits 解決單繼承限制,讓類能水平組合行為。Trait 類似類但不能實例化,通過 use 關鍵字在類中引入。本文系統講解核心用法與進階技巧。
trait Logger {
public function log($msg) { echo "[LOG] $msg\n"; }
}
trait Timestamp {
public function now() { return date('Y-m-d H:i:s'); }
}
class Service {
use Logger, Timestamp;
}
$svc = new Service();
$svc->log('服務啟動'); // [LOG] 服務啟動
echo $svc->now(); // 2024-01-15 10:30:00
trait A { public function foo() { echo 'A'; } }
class Base { public function foo() { echo 'Base'; } }
class Child extends Base { use A; public function foo() { echo 'Child'; } }
$c = new Child(); $c->foo(); // Child
同名方法引發 Fatal Error,需顯式指定:
trait A { public function test() { echo 'A'; } }
trait B { public function test() { echo 'B'; } }
class C {
use A, B {
B::test insteadof A; // 選用 B 的 test
A::test as testA; // 給 A 的 test 別名
}
}
$c = new C();
$c->test(); // B
$c->testA(); // A
trait Hello { public function say() { echo 'Hello'; } }
class A { use Hello { say as protected; } } // 變 protected
class B { use Hello { say as private myHello; } } // 變私有並改名
$b = new B();
// $b->say(); // Fatal: protected
// $b->myHello(); // 可在 B 內部調用
trait A { public function a() { echo 'a'; } }
trait B { public function b() { echo 'b'; } }
trait C { use A, B; } // Trait 組合 Trait
class D { use C; }
$d = new D(); $d->b(); // b
// 靜態變量在 Trait 方法中共享
trait Counter {
public function inc() { static $c = 0; echo ++$c; }
}
class X { use Counter; }
class Y { use Counter; }
$x = new X; $x->inc(); // 1
$y = new Y; $y->inc(); // 1(各類獨立)
trait Validatable {
abstract public function rules(); // 強制實現類定義
public function validate() { /* 通用驗證邏輯 */ }
}
Trait 定義的屬性若在使用類中同名定義會報錯(嚴格模式下)。建議 Trait 僅定義方法,屬性由類自行管理。