2012-02-02 5 views
5

un po 'curioso, ma voglio fare una serie di classi che ho dichiarato di usare qualcosa di simileuso get_declared_class() per solo ouput che le classi non dichiarati quelli PHP fa automaticamente

foreach(get_declared_classes() as $class) 
    $c[] = $class; 


print_r($c); 

l'unico problema con questo è che ottengo qualcosa di simile sulla parte superiore delle mie classi caricate:

stdClass 
Exception 
ErrorException 
Closure 
DateTime 
DateTimeZone 
DateInterval 
DatePeriod 
LibXMLError 
LogicException 
BadFunctionCallException 
BadMethodCallException 
DomainException 
InvalidArgumentException 
LengthException 
OutOfRangeException 
RuntimeException 
OutOfBoundsException 
OverflowException 
RangeException 
UnderflowException 
UnexpectedValueException 
RecursiveIteratorIterator 
IteratorIterator 
{...} 
SQLiteResult 
SQLiteUnbuffered 
SQLiteException 
SQLite3 
SQLite3Stmt 
SQLite3Result 
XMLReader 
XMLWriter 
XSLTProcessor 
ZipArchive 

c'è una funzione che carica solo specifiche classi di utenti, piuttosto che classi caricate di sistema? o forse una dichiarazione di condizione che limita lo foreach per elencare quelle classi?

+3

FWIW: Il tuo ciclo sta facendo la stessa cosa come un semplice 'print_r (get_declared_classes())'. Non risponde alla tua domanda, ma semplifica il codice. – deceze

+0

@eli, vedi la mia risposta. Fornisce una soluzione che non implica variabili globali e non influisce sulle prestazioni. Probabilmente dovresti aggiornare la risposta accettata. https: // StackOverflow.com/a/46126712/1050262 –

risposta

1

Ecco la mia soluzione che funziona effettivamente e non influisce sulle prestazioni. Questo ti dà solo le classi definite nel tuo progetto, nient'altro. Assicurati di eseguirlo il più tardi possibile, dopo aver caricato tutte le classi.

/** 
* Get all classes from a project. 
* 
* Return an array containing all classes defined in a project. 
* 
* @param string $project_path 
* @return array 
*/ 
function smk_get_classes_from_project($project_path){ 
    // Placeholder for final output 
    $classes = array(); 

    // Get all classes 
    $dc = get_declared_classes(); 

    // Loop 
    foreach ($dc as $class) { 
     $reflect = new \ReflectionClass($class); 

     // Get the path to the file where is defined this class. 
     $filename = $reflect->getFileName(); 

     // Only user defined classes, exclude internal or classes added by PHP extensions. 
     if(! $reflect->isInternal()){ 

      // Replace backslash with forward slash. 
      $filename = str_replace(array('\\'), array('/'), $filename); 
      $project_path = str_replace(array('\\'), array('/'), $project_path); 

      // Remove the last slash. 
      // If last slash is present, some classes from root will not be included. 
      // Probably there's an explication for this. I don't know... 
      $project_path = rtrim($project_path, '/'); 

      // Add the class only if it is defined in `$project_path` dir. 
      if(stripos($filename, $project_path) !== false){ 
       $classes[] = $class; 
      } 

     } 
    } 

    return $classes;  
} 

Testarlo.

questo esempio si presuppone che il progetto ha questo percorso: /srv/users/apps/my-project-name

echo '<pre>'; 
print_r(smk_get_classes_from_project('/srv/users/apps/my-project-name')); 
echo '</pre>'; 
11

Non esiste alcuna funzione incorporata per ottenere ciò, ma è possibile effettuare lo get_declared_classes appena prima di dichiarare qualsiasi cosa e memorizzarlo nella variabile globale, ad esempio $predefinedClasses. Poi, in cui è necessario utilizzare:

print_r(array_diff(get_declared_classes(), $predefinedClasses)); 
4

c'è nessun direttamente incorporati possibilità per questo, ma è possibile effettuare le seguenti operazioni:

  1. proprio all'inizio dello script, chiamare get_declared_classes() e savve esso ad una variabile come $php_classes
  2. dopo aver caricato le tue lezioni, chiamare get_declared_classes() di nuovo e utilizzare array_diff() per filtrare il $php_classes - il risultato è un elenco delle proprie classi.

    // start 
    $php_classes = get_declared_classes(); 
    
    // ... 
    // some code loading/declaring own classes 
    // ... 
    
    // later 
    $my_classes = array_diff(get_declared_classes(), $php_classes); 
    
+0

posso usarlo in un ambito globale all'interno di un costrutto? – Eli

+0

$ GLOBALS ['php_classes'] si adatterebbe – dmitry

+0

grazie, stavo per chiedere come usare una variabile globale nella constuct =) – Eli

13

l'API Reflection grado di rilevare se una classe è interna o meno:

Esempio (demo/alternate):

$userDefinedClasses = array_filter(
    get_declared_classes(), 
    function($className) { 
     return !call_user_func(
      array(new ReflectionClass($className), 'isInternal') 
     ); 
    } 
); 

Il codice sopra controllerà e rimuoverà ogni classe restituita da get_declared_classes che è interna, lasciando solo le classi definite dall'utente. In questo modo, non è necessario creare e mantenere una serie di classi interne come suggerito altrove in questa pagina.

+0

in quel contesto qual è la variabile '$ className'? – Eli

+0

@ s2xi 'get_declared_classes' restituisce una matrice di nomi di classi. 'array_filter' passerà ognuno di questi nomi di classe alla funzione anonima (il' $ className') e rimuoverà quelli dall'array per il quale la funzione anonima restituisce 'false'. La funzione anonima creerà una nuova istanza ReflectionClass per quel nome di classe e restituirà il risultato di 'ReflectionClass :: isInternal' (un booleano). '!' Nega il risultato perché vogliamo solo consentire classi che non sono interne. – Gordon

+0

@ s2xi controlla la versione alternativa che ho collegato. potrebbe essere più facile da capire. – Gordon

Problemi correlati