Get declared traits: примеры (PHP)

Использование get_declared_traits для работы с трейтами в PHP
Раздел: Объектно-ориентированное программирование
get_declared_traits: array

Описание функции get_declared_traits

Функция get_declared_traits() возвращает массив со всеми объявленными в текущем скрипте трейтами. Эта функция не принимает параметров. Она доступна начиная с PHP 5.4.0, где появилась поддержка трейтов.

Назначение и применение

Функция применяется для интроспекции кода, отладки, анализа зависимостей и построения систем автоматической документации. Она позволяет получить список всех трейтов, доступных в текущем контексте выполнения, включая трейты, объявленные в подключенных файлах и загруженные через автозагрузчик.

Простые примеры использования

Базовый вызов функции

Пример получения списка трейтов:

<?php
trait Loggable {
    public function log($msg) {
        echo $msg;
    }
}

trait Serializable {
    public function serialize() {
        return json_encode($this);
    }
}

$traits = get_declared_traits();
print_r($traits);
?>
Array
(
    [0] => Loggable
    [1] => Serializable
)
Проверка наличия трейта

Пример проверки, объявлен ли конкретный трейт:

<?php
trait MyTrait {}

if (in_array('MyTrait', get_declared_traits())) {
    echo 'Трейт MyTrait объявлен';
}
?>
Трейт MyTrait объявлен

Похожие функции в PHP

Возвращает массив объявленных классов. Может использоваться вместе с get_declared_traits() для полного анализа структуры кода.

class_uses()

Возвращает массив трейтов, используемых конкретным классом или объектом. В отличие от get_declared_traits(), показывает только примененные трейты.

trait_exists()

Проверяет существование трейта. Более эффективна для единичных проверок, чем поиск в массиве от get_declared_traits().

Аналоги в других языках

Python: интроспекция миксинов

В Python нет точного аналога, но можно получить список классов через globals() или модуль inspect:

import inspect

class MyMixin:
    pass

declared_mixins = [obj for name, obj in globals().items() 
                   if inspect.isclass(obj) and name.endswith('Mixin')]
print(declared_mixins)
[<class '__main__.MyMixin'>]
JavaScript: анализ прототипов

В JavaScript нет нативной поддержки трейтов, но в TypeScript можно использовать миксины:

// TypeScript
function applyMixins(derivedCtor: any, baseCtors: any[]) {
    baseCtors.forEach(baseCtor => {
        Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
            derivedCtor.prototype[name] = baseCtor.prototype[name];
        });
    });
}
// Конкретной функции для получения всех миксинов нет

Типичные ошибки

Ожидание параметров

Ошибка при передаче аргументов:

<?php
$traits = get_declared_traits(true); // Неверно
?>
Warning: get_declared_traits() expects exactly 0 parameters, 1 given
Непонимание области видимости

Функция возвращает только объявленные на момент вызова трейты:

<?php
$traitsBefore = get_declared_traits();
trait NewTrait {}
$traitsAfter = get_declared_traits();

echo 'До: ' . count($traitsBefore) . "\n";
echo 'После: ' . count($traitsAfter) . "\n";
?>
До: 0
После: 1

Изменения в версиях PHP

Функция появилась в PHP 5.4.0 вместе с введением трейтов. В PHP 5.4.0-5.4.3 функция могла возвращать некорректные результаты при использовании вместе с get_declared_classes(). Начиная с PHP 8.0.0, функция всегда возвращает корректный список, включая трейты, объявленные в теле класса.

Расширенные примеры

Фильтрация пользовательских трейтов

Отделение пользовательских трейтов от внутренних (если такие есть):

Пример php
<?php
trait CustomTrait1 {}
namespace MyProject;
trait CustomTrait2 {}

$allTraits = get_declared_traits();
$userTraits = array_filter($allTraits, function($traitName) {
    return strpos($traitName, 'MyProject\\') === 0 
           || strpos($traitName, 'CustomTrait') === 0;
});

print_r($userTraits);
?>
Array
(
    [0] => CustomTrait1
    [2] => MyProject\CustomTrait2
)
Анализ трейтов с рефлексией

Комбинирование с Reflection API для получения детальной информации:

Пример php
<?php
trait ExampleTrait {
    public function method1() {}
    protected function method2() {}
}

foreach (get_declared_traits() as $traitName) {
    $reflection = new ReflectionClass($traitName);
    echo "Трейт: $traitName\n";
    echo "Методы: " . implode(', ', 
        array_map(function($m) { 
            return $m->getName(); 
        }, $reflection->getMethods())
    ) . "\n\n";
}
?>
Трейт: ExampleTrait
Методы: method1, method2
Автозагрузка и трейты

Динамическая загрузка трейтов через автозагрузчик:

Пример php
<?php
spl_autoload_register(function($className) {
    if ($className === 'DynamicTrait') {
        eval("trait DynamicTrait { public function dyn() { return 'dynamic'; } }");
    }
});

// До загрузки
echo "До: " . (in_array('DynamicTrait', get_declared_traits()) ? 'Да' : 'Нет') . "\n";

// Триггер автозагрузки
class_exists('DynamicTrait');

// После загрузки
echo "После: " . (in_array('DynamicTrait', get_declared_traits()) ? 'Да' : 'Нет') . "\n";
?>
До: Нет
После: Да

PHP get_declared_traits function comments

En
Get declared traits Returns an array of all declared traits