2010-10-22 3 views
21

J'ai une interfacePHP: comment obtenir une liste de classes qui implémentent certaines interfaces?

interface IModule { 
    public function Install(); 
} 

et certaines classes qui mettent en œuvre cette interface

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; 
    } 
} 

Comment obtenir une liste de toutes les classes qui mettent en œuvre cette interface? Je voudrais obtenir cette liste avec PHP.

+2

Vous devriez probablement préciser si vous voulez obtenir la liste dans PHP ou si vous voulez juste générer une telle liste à des fins de documentation, etc. –

Répondre

20

Vous pouvez utiliser les fonctions PHP ReflectionClass::implementsInterface et get_declared_classes pour y parvenir:

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

Remarque: Cela ne fonctionne pas si vous chargez des IModules via '__autoload'. Mais +1. –

+0

7 ans de retard de commentaire, mais voici un exemple de la façon dont vous pouvez utiliser les fichiers dans Composers autoload pour s'assurer que certains fichiers spécifiques seront chargés à chaque fois et être disponibles avec get_declared_classes: http://stackoverflow.com/a/18671530/143279 – bleakgadfly

40

Vous ne avez pas besoin de réflexion pour cela. Vous pouvez simplement utiliser

  • class_implements - Retourne les interfaces qui sont mises en œuvre par la classe donnée

Utilisation

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

Exemple 1 - Echo toutes les classes implémentant l'interface Iterator

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

Exemple 2 - Retourne un tableau de toutes les classes implémentant l'interface Iterator

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

Le deuxième exemple nécessite PHP5.3 en raison de la fonction de rappel étant une fonction anonyme.

11

solution générique:

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

Pour vérifier qui implémente une interface particulière, vous pouvez écrire une fonction comme ci-dessous:

<?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; 
    } 
} 

sortie d'un appel exemple var_export(whoImplements('ArrayAccess')); sera le suivant:

[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

De cette façon, vous n'utilisez pas de boucles et vous pouvez exécuter le code sur les versions inférieures de PHP. –

+0

Avez-vous une idée de la raison pour laquelle je vois un tableau vide, bien que j'implémente définitivement l'interface? – Smalbil

+0

@Netbulae Il doit y avoir quelque chose qui ne va pas. Mettez votre code dans le codepad et partagez un lien. –

Questions connexes