intercepter un require_once
Hors ligneMalalam Le 16/02/2006 à 11:29 Profil de Malalam Configuration de Malalam

Hello,

je bloque rarement au point de poser une question, mais là...je ne parviens pas à mes fins et j'ai épuisé mes idées ;-)

La problématique est relativement simple :
je travaille sur un bug connu de mon script de documentation.
Le principe pour documenter des classes est simple : le fichier dans lequel se trouve la classe est choisi, et je fais un require_once dessus. Jusque là, tout va bien. Mais comme mon script remonte les classes héritées, j'ai dû faire un require_once sur toutes les classes uploadées, car, sans règle de nommage, je n'ai pas de moyen de savoir dans quel fichier se trouve la classe héritée.
Ca marche très bien (tant qu'on a pas 200 fichiers uploadés, évidemment, mais ça, c'est un autre problème) quand le fichier de la classe héritée se trouve "au-dessus", ou "avant" le fichier de la classe héritante dans le répertoire.
Mais si elle est après, le require_once du fichier de la classe héritante me sort évidemment une erreur, car il ne trouve pas la aclasse héritée (normal, elle n'a pas encore été incluse).

J'ai donc fait plusieurs tests :
@require_once ne plante plus, mais bloque par contre (évidemment, pas de message d'erreur, mais ça bloque quand même au require défaillant).
J'ai alors testé ça :



<?php
     $aDocs
= scandir ('classes');
     $aFlag = array_fill (0, count ($aDocs) - 1, 0);
     while (in_array (0, $aFlag)) {
          foreach ($aDocs as $clef => $obj) {
               if ($obj !== '.' && $obj !== '..') {
                    try {
                         require_once ('classes/'.$obj);
                         $aFlag[$clef] = 1;
                    } catch (Exception $e) {
                         continue;
                    }
               }
          }
     }
?>




Le but étanht de flagger les fichiers inclus, et, si on rencontre un problème lors d'une inclusion, on saute et on passe aau suivant. Et on reboucle tant que tous les fichiers n'ont pas été flaggés à 1.
Mais rien à faire, le require_once plante, même dans le bloc du try {}.

J'ai ensuite utilisé la bufferisation de sortie :




<?php
         $contents
= '';
     $aDocs = scandir ('classes');
     $aFlag = array_fill (0, count ($aDocs) - 1, 0);
     while (in_array (0, $aFlag)) {
          foreach ($aDocs as $clef => $obj) {
               if ($obj !== '.' && $obj !== '..') {
                    try {
                                        ob_start ();
                         require_once ('classes/'.$obj);
                         $aFlag[$clef] = 1;
                                        $contents .= ob_get_contents ();
                                        ob_end_clean ();
                    } catch (Exception $e) {
                         continue;
                    }
               }
          }
     }
        echo $contents;

?>


Mais pareil, le require_once plante lamentablement.
Idem avec un @, je précise.

Je me suis alors lancé dans un $contents .= get_file_contents (...) à la place du require_once (), et un eval à la fin (voui je sais...mlais j'étais désespéré)
Mais là, ça tourne carrément trop longtemps au niveau du file_get_contents (je ne parle donc même pas du eval...).

Et là, je n'ai plus d'idée...
Alors si quelqu'un en avait une!! ;-)

Merci :-)

-------------------------------------------------------------------------

Ok, rajout. Voici une solution :

<?php
$aDocs
= scandir ('classes');
     foreach ($aDocs as $clef => $obj) {
          if ($obj !== '.' && $obj !== '..') {
               $content = file_get_contents ('classes/'.$obj);
               if( preg_match_all('@class\s+([\w\d_]+)\s+(extends\s+([\w\d_]+)\s+)?{@im',$content,$res) || preg_match_all('@class\s+([\w\d_]+)\s+(implements\s+([\w\d_]+)\s+)?{@im',$content,$res)) {
                    $aHierarchy[$res[1][0]]['parent'] = $res[3][0];
                    $aHierarchy[$res[1][0]]['file'] = $obj;
                   }
          }
     }
     $className = $_POST['nom'];
     $aIncs[] = $aHierarchy[$className]['file'];
     while (!empty ($aHierarchy[$className]['parent'])) {
          $className = $aHierarchy[$className]['parent'];
          $aIncs[] = $aHierarchy[$className]['file'];
     }
     $aIncs = array_reverse ($aIncs);
     foreach ($aIncs as $files) {
          require_once ('classes/'.$files);
     }
?>

Mais je ne suis pas arrivé à mettre l'atrenative entre extends et implements dans le même pattern... :-(
Hors ligneAnthony Le 16/02/2006 à 13:23 Profil de Anthony Configuration de Anthony

Admin
Salut Malalam :-)

((extends|implements)\s+([\w\d_]+)\s+)

ça devrait marcher par contre faut changer le numéro des $maches qui seront retournés pas la fonction ;-)
--

Hors ligneMalalam Le 16/02/2006 à 13:30 Profil de Malalam Configuration de Malalam

Voué, merci Antho :-) Parfait!

Le code complet :


<?php
if  
(isset ($_POST['documenter']) && $_POST['documenter'] === $oloc -> getMsg ('gui', 'app_document') && !empty ($_POST['objet']) && !empty ($_POST['nom'])) {
     $aDocs = scandir ('classes');
     foreach ($aDocs as $clef => $obj) {
          if ($obj !== '.' && $obj !== '..') {
               $content = file_get_contents ('classes/'.$obj);
               if (preg_match_all('@class\s+([\w\d_]+)(\s+(extends|implements)\s+([\w\d_]+))?\s*{@im',$content,$res)) {
                    foreach ($res[1] as $clef => $val) {
                         $aHierarchy[$res[1][$clef]]['parent'] = $res[4][$clef];
                         $aHierarchy[$res[1][$clef]]['file'] = $obj;
                    }
                   }
          }
     }
     $className = $_POST['nom'];
     $aIncs[] = $aHierarchy[$className]['file'];
     while (!empty ($aHierarchy[$className]['parent'])) {
          $className = $aHierarchy[$className]['parent'];
          $aIncs[] = $aHierarchy[$className]['file'];
     }
     $aIncs = array_reverse ($aIncs);
     foreach ($aIncs as $files) {
          require_once ('classes/'.$files);
     }

     try {
          $doc = new odocclass ($_POST['nom']);
          $sError = $oloc -> getMsg ('gui', 'app_document_created').$_POST['objet'];
          //header ('Location: docs/'.$_POST['nom'].'/'.$_POST['nom'].'.html');
     } catch (Exception $e) {
          $sError = $oloc -> getMsg ('errors', 'failed_instance');
     }
}
?>

Vous avez résolu votre problème avec VIC ? Faites-le savoir sur les réseaux sociaux !
Vulgarisation-informatique.com
Cours en informatique & tutoriels