trait / use în PHP

Un trait este un bloc de metode și proprietăți pe care îl poți copia în mai multe clase cu use.

Sintaxă
trait Nume { ... }
class C { use Nume; }

Ce face trait / use

Pentru că o clasă poate extinde o singură clasă, codul comun pentru clase fără legătură între ele se pune într-un trait. Scrii use NumeTrait; în interiorul clasei și metodele din trait devin metodele clasei.

Un trait nu poate fi instanțiat singur. O clasă poate folosi mai multe trait-uri: use A, B;. Funcția class_uses arată ce trait-uri folosește o clasă.

Exemple

Exemplul 1: Același cod în două clase

<?php
trait AreSlug
{
    public function slug(): string
    {
        $text = strtolower(trim($this->titlu));
        return preg_replace('/[^a-z0-9]+/', '-', $text);
    }
}

class Articol
{
    use AreSlug;

    public function __construct(public string $titlu)
    {
    }
}

class Categorie
{
    use AreSlug;

    public function __construct(public string $titlu)
    {
    }
}

echo (new Articol("Cum instalezi PHP 8"))->slug() . "\n";
echo (new Categorie("Baze de date"))->slug();

Rezultat

cum-instalezi-php-8
baze-de-date

Exemplul 2: Trait cu proprietate și class_uses

<?php
trait Jurnal
{
    private array $mesaje = [];

    public function noteaza(string $mesaj): void
    {
        $this->mesaje[] = $mesaj;
    }

    public function jurnal(): array
    {
        return $this->mesaje;
    }
}

class Comanda
{
    use Jurnal;
}

$c = new Comanda();
$c->noteaza("Creată");
$c->noteaza("Plătită");
print_r($c->jurnal());
print_r(class_uses($c));

Rezultat

Array
(
    [0] => Creată
    [1] => Plătită
)
Array
(
    [Jurnal] => Jurnal
)

Greșeli frecvente

  • Confunzi use din clasă (care adaugă un trait) cu use de la începutul fișierului (care importă un nume dintr-un namespace). Sunt lucruri diferite.
  • Două trait-uri au o metodă cu același nume. PHP dă eroare fatală până rezolvi conflictul cu insteadof: use A, B { A::salut insteadof B; }.

Comenzi înrudite

  • class / new / $this: Definește o clasă: un șablon pentru obiecte care au date (proprietăți) și funcții proprii (metode).
  • extends / parent::: Creează o clasă nouă pornind de la una existentă (moștenire). Clasa copil primește tot ce are părintele.
  • interface / implements: O interfață este o listă de metode pe care o clasă promite să le aibă. Clasa le scrie cu implements.