Da trilha de PHP Este conceito ainda não saiu como card do dia. ir para o card de hoje

PHP POO Intermediário

Traits

Em PHP, uma trait é um mecanismo de reuso de código que permite compartilhar métodos entre classes sem herança. Diferente de interfaces, traits podem conter implementação concreta; diferente de classes abstratas, uma classe pode usar várias traits ao mesmo tempo. Isso resolve o problema da herança simples do PHP: você pode compor comportamentos de várias fontes.

A palavra-chave use importa uma trait para dentro de uma classe. Se duas traits trouxerem métodos com o mesmo nome, o PHP gera um erro fatal a menos que você resolva o conflito com insteadof (para escolher qual método usar) e as (para criar um alias). Traits também podem declarar métodos abstratos, obrigando a classe que as usa a implementá-los.

Use traits quando precisar compartilhar um conjunto coeso de métodos entre classes não relacionadas hierarquicamente. Evite usá-las como "colcha de retalhos": se o comportamento pertence a uma família de classes, prefira herança ou interfaces. Traits são ideais para funcionalidades transversais como logging, validação ou formatação.

Pontos-chave

  • use NomeDaTrait; dentro da classe importa todos os métodos da trait.
  • Conflitos de nomes entre traits são resolvidos com insteadof (escolhe um) e as (cria alias).
  • Traits podem declarar métodos abstratos, forçando a classe a implementá-los.
  • Uma classe pode usar múltiplas traits, contornando a herança simples do PHP.
  • Prefira traits para comportamentos reutilizáveis e independentes de hierarquia.
traits_demo.php
<?php
// Trait com método concreto
trait Loggable {
    public function log(string $msg): void {
        echo "[LOG] $msg\n";
    }
}

// Trait com método abstrato
trait Validatable {
    abstract public function rules(): array;

    public function validate(array $data): bool {
        foreach ($this->rules() as $field => $rule) {
            if ($rule === 'required' && empty($data[$field])) {
                return false;
            }
        }
        return true;
    }
}

// Trait com método que conflita
trait JsonExport {
    public function export(): string {
        return json_encode(get_object_vars($this));
    }
}

trait XmlExport {
    public function export(): string {
        return '<user>' . htmlspecialchars($this->name) . '</user>';
    }
}

class User {
    use Loggable, Validatable, JsonExport, XmlExport {
        // Resolve conflito: usa export do JsonExport e cria alias do Xml
        JsonExport::export insteadof XmlExport;
        XmlExport::export as exportXml;
    }

    public function __construct(public string $name) {}

    public function rules(): array {
        return ['name' => 'required'];
    }
}

$user = new User('Ana');
$user->log('Usuário criado');
echo $user->export() . "\n";
echo $user->exportXml() . "\n";
var_dump($user->validate(['name' => 'Ana']));
var_dump($user->validate(['name' => '']));

Exercícios

  1. 1
    Fácil

    Trait de saudação

    Crie uma trait Saudacao com o método dizerOla() que retorna "Olá, " . $this->nome. Depois, crie a classe Pessoa que usa a trait e tem a propriedade $nome definida no construtor. Instancie Pessoa('Maria') e imprima o retorno de dizerOla().

    Resolver
  2. 2
    Médio

    Conflito entre traits

    Crie duas traits: A com método falar() que retorna "A" e B com método falar() que retorna "B". Crie a classe C que usa ambas as traits, resolve o conflito usando insteadof para preferir o método de A e cria um alias falarB para o método de B. Instancie C e imprima o retorno de falar() e falarB() em linhas separadas.

    Resolver
  3. 3
    Desafio

    Trait com método abstrato e validação

    Crie uma trait Validavel com um método abstrato regras(): array e um método concreto validar(array $dados): bool que retorna false se algum campo obrigatório estiver vazio, e true caso contrário. Crie duas classes: Usuario e Produto, cada uma usando a trait e implementando regras() com campos diferentes. Teste com dados válidos e inválidos para cada classe.

    Resolver

Continue estudando