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

Функция get_declared_interfaces в PHP 8: полный обзор с примерами
Раздел: Объектно-ориентированное программирование
get_declared_interfaces: array
Описание функции get_declared_interfaces

Функция get_declared_interfaces() возвращает массив с именами всех объявленных в текущем скрипте интерфейсов. Эта функция не требует аргументов и всегда возвращает индексированный массив строк.

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

Аргументы функции

Функция не принимает параметров.

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

Пример получения всех объявленных интерфейсов:

<?php
// Объявляем пару интерфейсов
interface MyInterface {}
interface AnotherInterface {}

// Получаем массив всех интерфейсов
$allInterfaces = get_declared_interfaces();

// Выводим результат
print_r($allInterfaces);
?>
Array
(
    [0] => Traversable
    [1] => IteratorAggregate
    [2] => Iterator
    [3] => ArrayAccess
    ...
    [24] => MyInterface
    [25] => AnotherInterface
)

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

<?php
interface LoggerInterface {}

$interfaces = get_declared_interfaces();

if (in_array('LoggerInterface', $interfaces)) {
    echo 'Интерфейс LoggerInterface объявлен.';
}
?>
Интерфейс LoggerInterface объявлен.
Похожие функции в PHP

get_declared_classes() возвращает массив с именами объявленных классов. Полезна для анализа структуры классов в скрипте.

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

get_declared_traits() (появилась в PHP 5.4) возвращает массив с именами всех объявленных трейтов. Используется для работы с трейтами аналогично get_declared_interfaces().

class_implements() возвращает массив интерфейсов, реализованных указанным классом или объектом. Полезна для анализа конкретного класса, а не всей системы.

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

Get declared interfaces в Python

В Python нет прямой аналогии, но похожую информацию можно получить через модуль inspect или __subclasses__() для ABC (Abstract Base Classes). Отличие в том, что Python не разделяет понятия интерфейса и абстрактного класса так строго.

import abc

class MyInterface(abc.ABC):
    @abc.abstractmethod
    def method(self):
        pass

# Получить все подклассы абстрактного класса нельзя напрямую.
# Обычно используется регистрация или другие паттерны.
JavaScript (Node.js)

В JavaScript (ES6+) интерфейсов как отдельной конструкции нет. Аналогичную роль играют классы или проверка структуры объектов (утиная типизация).

// Нет встроенной функции для получения всех "интерфейсов"
// Можно эмулировать через наборы классов или символов.

Get declared interfaces в Java

В Java можно использовать Reflection API для получения списка интерфейсов, загруженных в ClassLoader. Отличие в статической типизации и необходимости работать через ClassLoader.

import java.lang.reflect.*;

public class Main {
    public static void main(String[] args) {
        // Получение всех загруженных интерфейсов не является стандартной операцией.
        // Обычно анализируют конкретный класс или пакет.
    }
}
Типичные ошибки

Ошибка неправильной интерпретации результата: функция возвращает имена интерфейсов как строки, а не объекты.

<?php
$interfaces = get_declared_interfaces();

// Попытка использовать имя интерфейса как класс (ошибка)
foreach ($interfaces as $interface) {
    // $interface - это строка, а не объект интерфейса.
    // new $interface(); // Приведет к фатальной ошибке, так как интерфейсы нельзя инстанциировать.
}
?>

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

<?php
interface MyCaseInterface {}

$interfaces = get_declared_interfaces();

// in_array чувствительна к регистру по умолчанию
if (in_array('mycaseinterface', $interfaces)) { // false
    echo 'Интерфейс найден.';
} else {
    echo 'Интерфейс не найден (проблема регистра).';
}
?>
Интерфейс не найден (проблема регистра).
Изменения в последних версиях PHP

В PHP 8.0 и 8.1 не было внесено значительных изменений в поведение функции get_declared_interfaces(). Функция остается стабильной и обратно совместимой. Единственные изменения связаны с добавлением новых встроенных интерфейсов в ядро PHP с выходом новых версий, например, интерфейсов для поддержки Fiber в PHP 8.1.

Расширенные примеры использования

Пример анализа интерфейсов в пространствах имен:

Пример php
<?php
namespace App\Contracts;

interface ServiceInterface {}
interface RepositoryInterface {}

namespace App\Services;

use App\Contracts\ServiceInterface;

class MyService implements ServiceInterface {}

// Получаем все интерфейсы
$all = get_declared_interfaces();

// Фильтруем интерфейсы по пространству имен
$appInterfaces = array_filter($all, function($interface) {
    return strpos($interface, 'App\\') === 0;
});

print_r($appInterfaces);
?>
Array
(
    [24] => App\Contracts\ServiceInterface
    [25] => App\Contracts\RepositoryInterface
)

Пример динамической проверки реализации интерфейсов классом:

Пример php
<?php
interface SerializableInterface {
    public function serialize();
}

class User implements SerializableInterface {
    public function serialize() {
        return 'serialized data';
    }
}

// Проверка через get_declared_interfaces и class_implements
$interfaces = get_declared_interfaces();
$userImplements = class_implements('User');

$common = array_intersect($interfaces, $userImplements);

if (in_array('SerializableInterface', $common)) {
    echo 'User реализует SerializableInterface.';
}
?>
User реализует SerializableInterface.

Пример использования для автозагрузки или регистрации сервисов:

Пример php
<?php
// Условный пример паттерна плагинов
interface PluginInterface {
    public function init();
}

class LoggerPlugin implements PluginInterface {
    public function init() {
        echo 'LoggerPlugin инициализирован.';
    }
}

class CachePlugin implements PluginInterface {
    public function init() {
        echo 'CachePlugin инициализирован.';
    }
}

// Автоматическая регистрация всех плагинов
$interfaces = get_declared_interfaces();
$classes = get_declared_classes();

foreach ($classes as $class) {
    $implements = class_implements($class);
    if (in_array('PluginInterface', $implements)) {
        $plugin = new $class();
        $plugin->init();
        echo "<br>";
    }
}
?>
LoggerPlugin инициализирован.
CachePlugin инициализирован.

PHP get_declared_interfaces function comments

En
Get declared interfaces Returns an array of all declared interfaces