Intercepter un require_once

Résolu
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 - 16 févr. 2006 à 11:31
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 - 17 févr. 2006 à 18:14
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 :-)

33 réponses

J_G Messages postés 1406 Date d'inscription mercredi 17 août 2005 Statut Membre Dernière intervention 28 août 2007 10
16 févr. 2006 à 11:55
Salut malalam.

Problème interessant... Je vais essayer de te donner une piste pour te décoincer (je dis bien "essayer").

Je pense que l'idée du scandir est bonne... mais pas assez exploitée.

C'est à dire, au lieu de charger (require_once) tous les fichiers contenant des classes, je te propose de plutôt parser ces fichiers.

Par exemple :
* Tu ouvre le répertoire du projet à documenter

* Tu parcours récurssivement le projet, soit tous les fichiers de type texte =>
preg_match('@^text/@',mime_content_type($file));

* enfin tu parses chacun de ces fichiers pour trouver des définition de classes
$content = file_get_contents($file);
if( preg_match_all('@class\s+([\w\d_]+)\s+(extends\s+([\w\d_]+)\s+)?{@im',$content,$res) ) {
/* ici, tu retrouve les classes et leur héritage dans $res */
$file; // le fichier qui contient des définitions de classes
$res[1]; // les noms des classes définies
$res[3]; // les classe parentes de ces dernières
}


* Avec ces infos, tu te construis un tableau, un arbre, des objets, ... tout ce que tu veux pour ensuite pouvoir le parcourir et retrouver facilement les fichier à inclure pour tel ou tel héritage.

Voilà, je ne pense pas que cette passe de parsing soit trop longue et 'espère que ça pourra t'aider...

A+ et bonne chance
3
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
16 févr. 2006 à 13:25
Bon vlà le résultat qui fonctionne à merveille :

<?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([mailto:'@class\s+([\w\d_]+)\s+((extends|implements)\s+([\w\d_]+)\s+)?{@im',$content,$res '@class\s+([\w\d_]+)\s+((extends|implements)\s+([\w\d_]+)\s+)?{@im',$content,$res])) {
$aHierarchy[$res[1][0]]['parent'] = $res[4][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);
}
}
?>

Meci à J_G, et à Anthomicro :-)
3
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
16 févr. 2006 à 15:53
Voilà, le code complet :

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([mailto:'@class\s+([\w\d_]+)\s+((extends|implements)\s+([\w\d_]+)\s+)?{@im',$content,$res '@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');
}
}
3
J_G Messages postés 1406 Date d'inscription mercredi 17 août 2005 Statut Membre Dernière intervention 28 août 2007 10
16 févr. 2006 à 17:17
Ouai non... Ca change rien.

Le préprocesseur va un peu plus galérer dans la première version. Mais une fois le script pré-maché (c'est à dire uniquement la première fois qu'il est exécuté) c'est quasiment pareil.

Note : Il y'a un risque de bug avec la RegExp...
class salut{/*...*/} ne colle pas et pourtane elle est bien déclarée ! (=> il n'y a pas d'espace entre le nom et l'accolade)
Correction proposée :
[http:// class\s+([\w\d_]+)(\s+(extends|implements)\s+([\w\d_]+))?\s*{]

A+
3

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
16 févr. 2006 à 12:17
Hello J_G,

j'avais pensé au parsing en effet, mais je pensais que ce serait trop long et fastidieux...ceci dit, vue que je me retrouve bien coincé là...et que ce que tu me montres est plus abouti que ce à quoi j'avais pensé, je vais tenter le coup.
Ca permettrait en plus de résoudre le problème des require inutiles.

Donc, je teste ça de suite :-) Merci J_G!
0
J_G Messages postés 1406 Date d'inscription mercredi 17 août 2005 Statut Membre Dernière intervention 28 août 2007 10
16 févr. 2006 à 12:22
De rien... surtout que je te laisse le plus dur à faire :

La structure du tableau/arbre à parcourir et les fonction de parcours. Ces exercices algorithmiques sont mes pire casses-têtes.

A+
0
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
16 févr. 2006 à 12:31
Je suis dessus lol...je réflêchis à la meilleure structure pour avoir un arbre facile à remonter. Et effecivement, ce sont les pires casse-têtes :-( Mais c'est rigolo!
J'ai ajouté implements dans ton pattern au fait, comme choix entre exteneds et implements (pour les interfaces).
Et sinon, ton pattern marche à merveille :-)
0
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
16 févr. 2006 à 13:34
Bon, l'acceptation ne marche pour le moment pas, alors j'accepterai la réponse plus tard :-)
0
J_G Messages postés 1406 Date d'inscription mercredi 17 août 2005 Statut Membre Dernière intervention 28 août 2007 10
16 févr. 2006 à 13:51
Bravo...
0
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
16 févr. 2006 à 14:07
Bah j'ai pas de mérite lol, tu m'as mâché tout le travail :-)
Antho m'a aidé à comprendre pq mon pattern marchait mal (en fait, il marchait très bien, j'avais juste oublié que les offset bougeaient...).
Quant à la hiérarchie, ça a finalement été très simple, comme tu peux le voir :-)
0
J_G Messages postés 1406 Date d'inscription mercredi 17 août 2005 Statut Membre Dernière intervention 28 août 2007 10
16 févr. 2006 à 14:13
Oui, c'est pour ça que je dis "bravo"... je ne le voyais pas si simple.

Par contre, j'ai l'impression que tu ne prends pas en compte le fait qu'il puisse y avoir plusieur définition de classe dans un même fichier. Par exemple parent + enfant.

C'est pour ça que je t'ai indiqué le preg_match_all

Voilou.
A+
0
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
16 févr. 2006 à 14:29
C'est exact lol. Mais c'est pas un problème. Je dois juste modifier la façon de construire le tableau hiérarchique c'est tout. Je vais le faire de ce pas d'ailleurs ;-)
0
J_G Messages postés 1406 Date d'inscription mercredi 17 août 2005 Statut Membre Dernière intervention 28 août 2007 10
16 févr. 2006 à 15:59
Ben super... c'était pas grand chose :)

Et niveau timing : correct ?
0
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
16 févr. 2006 à 16:34
Très, aucun problème contrairement à ce que je pensais.
Tu avais raison :-) Je n'ai pas fait de bench pour comparer, mais disons qu'à l'oeuil nu, on ne voit aucune différence avec avant. De plus, avec ton système, les pages vont être bcp plus légères même avec bcp de classes uploadées, puisqu'on inclut plus que les classes à analyser :-) Donc c'est bien mieux qu'avant ! :-)

Je pourrais remplacer
$aHierarchy[$res[1][$clef]]['parent'] = $res[4][$clef];
$aHierarchy[$res[1][$clef]]['file'] = $obj;

par

$aHierarchy[$val]['parent'] = $res[4][$clef];
$aHierarchy[$val]['file'] = $obj;

mais bon, je ne pense pas que ça change grand chose...
0
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
16 févr. 2006 à 17:22
Oui j'y ai pensé...puis je n'y ai plus pensé ;-)
Je vais changer, effectivement. Faut faire gaffe à ça, façon d'écrire un code. Moi, je mets des espaces partout, d'autres pas (toi, par exemple, lol : fonction(bla) et fonction (bla) ou fonction( bla ) ou fonction ( bla )...c'est chiant lol).
0
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
16 févr. 2006 à 17:49
Voilà, c'est fait, et apparemment, ça marche :-)
Merci encore.
Mon application commence sérieusement à prendre forme ;-)
je suis maintenant juste un peu à court d'idée pour la faire encore évoluer lol ;-)
0
J_G Messages postés 1406 Date d'inscription mercredi 17 août 2005 Statut Membre Dernière intervention 28 août 2007 10
16 févr. 2006 à 17:55
Elle fait quoi ton application ?

Enfin, je veux dire... Elle documente que les classses ou elle fait des diagrammes d'héritage et de la doc sur les fonctions ?
Est-ce qu'elle énumère aussi les implémentations des classes/fonctions ?

(Et si elle fait tout ça... je peux l'avoir ?)
0
FhX Messages postés 2350 Date d'inscription mercredi 13 octobre 2004 Statut Membre Dernière intervention 18 avril 2015 3
16 févr. 2006 à 18:09
J'ai même pas eu le temps de me pencher sur le problème que c'est déja résolu...

Rahhh, chui encore malade 4 jours et y se passe un tas de trucs !!
0
J_G Messages postés 1406 Date d'inscription mercredi 17 août 2005 Statut Membre Dernière intervention 28 août 2007 10
16 févr. 2006 à 18:13
Faut pas être malalade avec Internet ;)
0
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
16 févr. 2006 à 18:15
Ben heu sers-toi lol :
http://www.phpcs.com/codes/PHP5-CLASSE-DOCUMENTATION-CLASSES-FONCTIONS_35950.aspx

Elle documente automatiquement les classes (remonte la hiérarchie s'il y en a une, comme tu l'as compris lol), ainsi que les fichiers de fonctions.

Bref, tu uploades tes fichiers de classes, tes fichiers de fonctions.
Puis tu choisis les fichiers que tu veux documenter, et hoip c'est fait : elle crée des fichiers html pourt la doc.
Enfin, je te laisse regarder , j'ai mis dans le zip des exemples de documentation créées. C'est très facile à utiliser.

Pour le moment, elle ne fait pas de diagramme mais c'est une super idée lol!
J'ai même une idée pour ce propos...générer ça par package (pour l'instant, c'est généré par classe/fichier de fonctions), cxela permattrait de browser un package plus facilement. Et de créer un diagramme du package justement.

Et comme ça, si tu testes, tu pourras me donner des idées :-) Et des suggestions d'améliorations. C'est un projet qui me plait et sur lequel j'aime bien passer du temps (j'ai commencé y a 5-6 jours je crois, pdt mes pauses au boulot lol).
0
Rejoignez-nous