Trait 特性详解
Trait 是 PHP 5.4 引入的代码复用机制,解决了单继承的局限性。
基础用法
php
trait Logger {
public function log($message) {
echo "[" . date('Y-m-d H:i:s') . "] $message\n";
}
}
class UserController {
use Logger;
public function create() {
$this->log('创建用户');
}
}
$user = new UserController();
$user->create(); // [2024-01-01 12:00:00] 创建用户使用多个 Trait
php
trait Validator {
public function validate($data, $rules) {
// 验证逻辑
return true;
}
}
trait Responsable {
public function json($data) {
header('Content-Type: application/json');
return json_encode($data);
}
}
class ApiController {
use Logger, Validator, Responsable;
}解决冲突
php
trait A {
public function sayHello() {
echo 'Hello from A';
}
}
trait B {
public function sayHello() {
echo 'Hello from B';
}
}
class MyClass {
use A, B {
// 使用 A 的方法,B 的方法重命名为 sayHelloB
A::sayHello insteadof B;
B::sayHello as sayHelloB;
}
}
$obj = new MyClass();
$obj->sayHello(); // Hello from A
$obj->sayHelloB(); // Hello from B修改访问修饰符
php
trait MyTrait {
public function publicMethod() {}
protected function protectedMethod() {}
}
class MyClass {
use MyTrait {
// 改为私有
publicMethod as private;
// 改为公共并重命名
protectedMethod as public publicAlias;
}
}Trait 中访问宿主类属性
php
trait Timestampable {
public function touch() {
$this->updated_at = date('Y-m-d H:i:s');
}
}
class Post {
use Timestampable;
public $updated_at;
}
$post = new Post();
$post->touch();
echo $post->updated_at;Trait 组合
php
trait BaseTrait {
public function baseMethod() {
return 'base';
}
}
trait ExtendedTrait {
use BaseTrait;
public function extendedMethod() {
return $this->baseMethod() . ' + extended';
}
}
class MyClass {
use ExtendedTrait;
}抽象方法和静态方法
php
trait Configurable {
abstract public function getConfigKey();
public function getConfig() {
return config($this->getConfigKey());
}
public static function createWithConfig() {
$instance = new static();
$instance->config = $instance->getConfig();
return $instance;
}
}
class Database {
use Configurable;
public function getConfigKey() {
return 'database';
}
}注意事项
- Trait 不能有常量(PHP 8.2 起支持)
- Trait 优先级:当前类 > Trait > 父类
- 过多使用 Trait 可能导致代码难以追踪
- Trait 不是类,不能实例化