Трейты

31 Октября 2022 00:26

Документация - https://www.php.net/manual/ru/language.oop5.traits.php

Как гласит документация, Трейты реализуют метод для повторного использования кода.

Проще говоря, это набор методов/свойств, которые можно собрать в одном месте и подключать в нужном классе для использования.

Добавлять можно сколько угодно трейтов.

Синтаксис

<?php

namespace App\Models\Traits;

use Illuminate\Support\Carbon;

trait HasDates
{
    public function getCreatedAtAttribute($value)
    {
        $date = Carbon::parse($value);

        return $date->format('Y-m-d H:i:s');
    }

    public function getUpdatedAtAttribute($value)
    {
        $date = Carbon::parse($value);

        return $date->format('Y-m-d H:i:s');
    }
}

Пример трейта с laravel. Как видно, в трейте можно объявить namespace, подключить другие классы и объявить методы.

Подключение трейтов

<?php

use App\Models\Traits\HasDates;

class User extends Model {
    use HasDates;
    /* ... */
}

Приоритет

При совпадении имен методов в трейте и классах, одни будут заменены другими.

Порядок: Метод в классе -> Метод в трейте -> Унаследованный метод.

То есть самый главный метод будет в классе, потом в трейте и самый последний - унаследованный.

Разрешение конфликтов

При подключении нескольких трейтов, если в них совпадают имена методов то будет выдана фатальная ошибка, если конфликты имен не разрешены явно.

Есть несколько основных способов разрешения конфликтов:

  1. Оператор insteadof;
  2. Оператор as.
<?php

trait A {
    public function smallTalk() {
        echo 'a';
    }
    public function bigTalk() {
        echo 'A';
    }
}

trait B {
    public function smallTalk() {
        echo 'b';
    }
    public function bigTalk() {
        echo 'B';
    }
}

class Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
    }
}

class Aliased_Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
        B::bigTalk as talk;
    }
}