Skip to content

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';
    }
}

注意事项

  1. Trait 不能有常量(PHP 8.2 起支持)
  2. Trait 优先级:当前类 > Trait > 父类
  3. 过多使用 Trait 可能导致代码难以追踪
  4. Trait 不是类,不能实例化

Binstork