2010-10-22 4 views
21

У меня есть это интерфейсPHP: как получить список классов, реализующих определенный интерфейс?

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.

+2

Возможно, вам следует уточнить, хотите ли вы получить список на PHP или просто хотите создать такой список для целей документации и т. д. –

ответ

20

Вы можете использовать ReflectionClass::implementsInterface и get_declared_classes функции PHP для достижения этой цели:

$classes = get_declared_classes(); 
$implementsIModule = array(); 
foreach($classes as $klass) { 
    $reflect = new ReflectionClass($klass); 
    if($reflect->implementsInterface('IModule')) 
     $implementsIModule[] = $klass; 
} 
+5

Примечание: Это не работает, если вы загружаете модули с помощью '__autoload'. Но +1. –

+0

7-летний поздний комментарий, но вот пример того, как вы можете использовать файлы в автозагрузке Composers, чтобы гарантировать, что некоторые конкретные файлы будут загружаться каждый раз и будут доступны с помощью get_declared_classes: http://stackoverflow.com/a/18671530/143279 – bleakgadfly

40

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

  • 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 из-за обратный вызов, являющийся анонимная функция.

11

Generic решение:

function getImplementingClasses($interfaceName) { 
    return array_filter(
     get_declared_classes(), 
     function($className) use ($interfaceName) { 
      return in_array($interfaceName, class_implements($className)); 
     } 
    ); 
} 
3

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

<?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 
) 

+0

Таким образом, вы не используете циклы, и вы можете запустить код в более низких версиях PHP. –

+0

У вас есть идея, почему я вижу пустой массив, хотя я определенно реализую интерфейс? – Smalbil

+0

@Netbulae Должно быть что-то не так. Поместите свой код в код и поделитесь ссылкой. –

Смежные вопросы