PHP: как получить список классов, реализующих определенный интерфейс? - PullRequest
28 голосов
/ 22 октября 2010

У меня есть интерфейс

interface IModule {
    public function Install();
}

и некоторые классы, которые реализуют этот интерфейс

class Module1 implements IModule {
    public function Install() {
        return true;
    }
}

class Module2 implements IModule {
    public function Install() {
        return true;
    }
}

...

class ModuleN implements IModule {
    public function Install() {
        return true;
    }
}

Как получить список всех классов, которые реализуют этот интерфейс? Я хотел бы получить этот список с помощью PHP.

Ответы [ 4 ]

46 голосов
/ 22 октября 2010

Вам не нужно отражение для этого. Вы можете просто использовать

  • class_implements - вернуть интерфейсы, реализованные данным классом

Использование

in_array('InterfaceName', class_implements('className'));

Пример 1. Вывод всех классов, реализующих интерфейс итератора

foreach (get_declared_classes() as $className) {
    if (in_array('Iterator', class_implements($className))) {
        echo $className, PHP_EOL;
    }
}

Пример 2. Возвращение массива всех классов, реализующих интерфейс итератора

print_r(
    array_filter(
        get_declared_classes(), 
        function ($className) {
            return in_array('Iterator', class_implements($className));
        }
    )
);

Во втором примере требуется PHP5.3, поскольку обратный вызов является анонимной функцией.

25 голосов
/ 22 октября 2010

Для этого можно использовать функции PHP ReflectionClass::implementsInterface и get_declared_classes:

$classes = get_declared_classes();
$implementsIModule = array();
foreach($classes as $klass) {
   $reflect = new ReflectionClass($klass);
   if($reflect->implementsInterface('IModule')) 
      $implementsIModule[] = $klass;
}
12 голосов
/ 01 сентября 2012

Универсальное решение:

function getImplementingClasses( $interfaceName ) {
    return array_filter(
        get_declared_classes(),
        function( $className ) use ( $interfaceName ) {
            return in_array( $interfaceName, class_implements( $className ) );
        }
    );
}
3 голосов
/ 06 ноября 2013

Чтобы проверить, кто реализует конкретный интерфейс, вы можете написать функцию, как показано ниже:

<?php
/**
 * Get classes which implement a given interface 
 * @param string $interface_name Name of the interface
 * @return array Array of names of classes. Empty array means input is a valid interface which no class is implementing. NULL means input is not even a valid interface name.
 */
function whoImplements($interface_name) {
    if (interface_exists($interface_name)) {
        return array_filter(get_declared_classes(), create_function('$className', "return in_array(\"$interface_name\", class_implements(\"\$className\"));"));
    }
    else {
        return null;
    }
}

Вывод примера вызова var_export(whoImplements('ArrayAccess')); будет выглядеть следующим образом: [sandbox]$ php whoimplementswhat.php Array ( [29] => CachingIterator [30] => RecursiveCachingIterator [38] => ArrayObject [39] => ArrayIterator [40] => RecursiveArrayIterator [48] => SplDoublyLinkedList [49] => SplQueue [50] => SplStack [55] => SplFixedArray [56] => SplObjectStorage [111] => Phar [112] => PharData )

Таким образом, вы не используете циклы и можете запускать свой код на более низких версиях PHP. Функция array_filter зацикливается внутри, но внутри механизма исполнения PHP (следовательно, более производительная, чем циклы, написанные в коде PHP).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...