Declarer des fonctions avec des noms dynamiques

Declarer des fonctions avec des noms dynamiques - PHP - Programmation

Marsh Posté le 17-02-2006 à 02:08:13    

Bonjour a tous.
Dans mes developpements PHP, je suis amené a faire un systeme de modules pour
etendre les fonctionalités de mon programme.
 
Il y a donc des fonctions de bases, et un repertoire "modules", contenant
des sous repertoires contenant chacun des fichiers de config et scripts relatifs
au fonctionnement du module.
 
Dans mon programme principal, j'ai une classe module, qui contient la fonction
"run_module($module_id)", qui execute le main() du module dont l'ID a été passé
en parametres, apres avoir fait un include des fichiers config idoines.
 
Le probleme etant que pour le premier module, tout va bien, mais au second,
forcement, php me dit qu'il ne peut pas redéclarer la fonction main!
 
Ce que je cherche est donc un moyen de déclarer une fonction ayant un nom dybamique:
je souhaiterais pouvoir avoir quelquechose du genre main_01() ou 01 serait l'ID du module, récupéré
dans ma base.
 
si je fais
$main_function="main_$module_id";
$main_function() appellera bien la fonction souhaitée, mais le probleme reste entier pour la déclaration...
Comment déclarer une fonction dont le nom n'est pas prévu a l'exécution?
 
A moins qu'il soit possible de procéder autrement?
 
J'ai pensé a rajouter "en dur" des chiffres dans le nom des main, mais cette solution ne s'avere
pas satisfaisante, puisqu'obligeant a tenir une trace de tous les chiffres attribués...
De plus, cela ne garantirait pas l'absence de conflits si des modules utilisateurs sont rajoutés...
 
Alors qu'avec le nom dynamique, je rajoute l'ID (unique dans la table necessaire au modules) du module...
 
QUelqu'un saurait il comment faire, ou aurait il une solution alternative a ce probleme?
(a la limite, si je pouvais detruire les fonctions, ça irait, mais c'est malheureusement impossible en php...)
 
Je precise que je cherche à produire du code PHP4.


Message édité par sky_99 le 17-02-2006 à 02:08:43

---------------
http://www.core-tx.com
Reply

Marsh Posté le 17-02-2006 à 02:08:13   

Reply

Marsh Posté le 17-02-2006 à 04:15:20    

Faut voir du côté de create_function() et function_exists(), je te laisse consulter la doc pour les détails :)

Reply

Marsh Posté le 17-02-2006 à 05:20:04    

je ne sais pas si ça répond à ta question, mais on sait jamais, au cas où, je réponds !
 
Tu peux utiliser un Command pattern (tiens un lien pris au pif : http://www.tweenpix.net/blog/index [...] nd-pattern )
 
tu réalises toutes les classes de tes modules avec les même noms de méthodes, mais des noms de classe différents (bref, même interface même si y en a pas en PHP4 (et non on repart pas sur un débat sur les interfaces en PHP5 :p)) :  
tu fais donc un switch pour instancier la bonne classe en fonction de l'action souhaitée.
Ensuite, toutes les méthodes appelées auront les même noms pour toutes les classes, donc tu as juste à les appeler, pas besoin de savoir quelle action est demandée


Message édité par Djebel1 le 17-02-2006 à 05:32:58
Reply

Marsh Posté le 17-02-2006 à 11:13:37    

ben pour repérer le main(), il suffit que la fonction concernée commence, par ex, par main_module1() et le tour est joué. Sinon, si tu veux absolument garder le nom main(), ben faut inclure uniquement les fichiers du module à exécuter et pas les autres...

Reply

Marsh Posté le 17-02-2006 à 13:54:45    

Bonjour a tous.
 
naceroth -> Il semblerait que ce soit exactement ce que je cherchais, merci!
 
Djebel1 -> Je vais m'y interesser egalement, car apres tout, une partie du systeme est fait en POO. Donc il serait peut etre plus coherent de tout faire en POO? (ou alors, je pourrais peut etre autoriser les deux, en definissant une variable "$module_coding_paradigm", et par la suite implementer le traitement objet du module concerné... ça serait plus sympa
pour l'utilisateur, non?) Ceci dit, cette solution semble necessiter beaucoup de code...  
 
rufo -> Si c'etait si simple, je n'aurais pas eu besoin de ce topic ;) Il est impossible de n'includer que les fichiers de configs du module,
et il nommer dans chaque module le main en fonction du module n'est pas non plus satisfaisant pour les raisons énnoncées plus haut...
Sans compter que cela ne résoudrait pas le probleme des autres fonctions du module : si deux modules possedent la fonction "view_list()" par exemple, le probleme se pose a nouveau...
 
Pour info, pour ceux qui auraient le meme probleme, voici la methode pour creer des fonctions ayant un nom unique,
en utilisant l'idée de naceroth, create_function() :

Code :
  1. $main = create_function('$argument1,$argument2',
  2. 'instruction1($variable1);
  3. instruction2($variable2);
  4. return $resultat;');
  5. $main(20,30);


La doc complete et officielle se trouve ici.


---------------
http://www.core-tx.com
Reply

Marsh Posté le 17-02-2006 à 14:10:00    

bof, être obliger de parser des fichiers "au vol" pour recréer le code php afin de générer dynamiquement des fonctions, c'est vraiment pas une solution élégante et elle nécessiterait la création d'un "parser" en php.
En plus, pour trouver la source d'un bug avec une solution pareille, tu vas pouvoir courir longtemps.
 
Depuis php4, il existe une notion d'objet, ca régle proprement, de maniére élégante et définitive le probléme de sky_99 . Pas besoin de se compliquer la tache inutilement.

Reply

Marsh Posté le 17-02-2006 à 14:35:44    

sky_99 a écrit :

Bonjour a tous.
 
...
rufo -> Si c'etait si simple, je n'aurais pas eu besoin de ce topic ;) Il est impossible de n'includer que les fichiers de configs du module,
et il nommer dans chaque module le main en fonction du module n'est pas non plus satisfaisant pour les raisons énnoncées plus haut...
Sans compter que cela ne résoudrait pas le probleme des autres fonctions du module : si deux modules possedent la fonction "view_list()" par exemple, le probleme se pose a nouveau...
 
...


 
Y'a un truc que je ne comprends pas. Si t'as l'ID du module à exécuter (cf le "run_module($module_id)" ), tu sais donc quel bout de code t'as besoin pour l'exécution. Donc tu sais ce que tu dois faire comme include, non?

Reply

Marsh Posté le 17-02-2006 à 14:39:55    

omega2 a écrit :

bof, être obliger de parser des fichiers "au vol" pour recréer le code php afin de générer dynamiquement des fonctions, c'est vraiment pas une solution élégante et elle nécessiterait la création d'un "parser" en php.
En plus, pour trouver la source d'un bug avec une solution pareille, tu vas pouvoir courir longtemps.
 
Depuis php4, il existe une notion d'objet, ca régle proprement, de maniére élégante et définitive le probléme de sky_99 . Pas besoin de se compliquer la tache inutilement.


 
Hmm, concernant l'objet, j'y ai pensé, et certes, ça diminue le probleme.
Ceci dit, il reste présent : On ne peut ni effacer, ni redéclarer une classe.
Donc, si je passe les modules en objet , chaque module etant une classe, il faudrait toujours que je puisse
déclarer des classes ayant un nom dynamique...
or, cela ne semble pas possible (ça a été ma deuxieme idée...)
Donc si il existe une solution permettant de creer des classes ayant un nom unique, je suis preneur...
 
Le probleme etant, je le rappelle, la possibilité d'extension du programme initial par l'utilisateur, qui entraine
le risque de voir deux classes porter le meme nom...
 
Donc si vous avez une solution permettant de supprimer une classe existante, de renommer une classe, ou mieux,  
de déclarer une classe ayant un nom variable, ça serait encore mieux!


---------------
http://www.core-tx.com
Reply

Marsh Posté le 17-02-2006 à 14:44:27    

t'aurais pas un ex du genre de code d'extension qui est utilisé (juste le squelette, la structure) parce que j'ai peur de comprendre : c'est l'utilisateur qui tape le code source php du nouveau module d'extension qui est exécuté???

Reply

Marsh Posté le 17-02-2006 à 14:59:07    

EN fait, le systeme gere diverses fonctions de base.
Mais le but est de rendre le tout le plus modulaire possible, et de permettre l'ajout de fonctionalités ulterieures
via des modules.
 
Donc celui ci place les modules dans les repertoires correspondants, et dans l'interface de gestion des modules,
il indique que tel module est présent a tel endroit. Celui ci reçoit donc un ID dans la table indexant les modules.
 
Dans la page ou l'utilisateur veut voir apparaitre le module, il choisit dans un menu déroulant
le module qu'il veut voir executé a l'endroit ou il le souhaite.
 
Le programme principal déclare donc un objet de type module, qui executera le main() du module concerné,
apres avoir chargé le fichier de config et de fonctions, ou le fichier class.php correspondant.
 
Le probleme est que si l'utilisateur décide d'ecrire lui meme des modules, il risque de leur donner le nom de modules
existant deja. Donc, si son module et le module du meme nom sont chargés, il y a un conflit sur les noms ,  
les noms des fonctions si on est pas en POO, ou le nom des classes definissant les deux modules si on est en POO.
 
hors POO, ça donnerait :

Code :
  1. run_module($id_module)
  2. {
  3. recuperer_données_module($id_module);
  4. charger_fichier_config($id_module)
  5. charger_fichier_fonctions($id_module)
  6. executer_fonction_main_module();//lance le main du module défini dans le fichier de fonctions
  7. }


 
En POO, ça donnerait:

Code :
  1. $mod1=new Module($id_module);
  2. $mod1->executer_fonction_main_module();
  3. Module($id_module)
  4. {
  5. recuperer_données_module($id_module);
  6. charger_fichier_classe($id_module)
  7. $var=new Nom_De_La_Classe_du_Module_particulier($arguments)
  8. }


 
Ou quelquechose du genre... peut etre avec extends et de l'heritage plutot, mais bon,
en gros, voici l'idée.
 
La problematique est donc : comment etre sur que deux classes n'auront pas le meme nom, sans pour autant avoir a tenir
une liste exhaustive des classes deja crées pourr divers modules...
Il faudrait donc pouvoir déclarer dynamiquement la classe, soit en ajoutant a son nom fixe une variable (id dans la table du module, unique par définition), soit en generant son nom d'une façon quelconque garantissant son unicité.

Message cité 2 fois
Message édité par sky_99 le 17-02-2006 à 15:18:29

---------------
http://www.core-tx.com
Reply

Marsh Posté le 17-02-2006 à 14:59:07   

Reply

Marsh Posté le 17-02-2006 à 15:30:21    

sky_99 a écrit :

EN fait, le systeme gere diverses fonctions de base.
Mais le but est de rendre le tout le plus modulaire possible, et de permettre l'ajout de fonctionalités ulterieures
via des modules.
 
Donc celui ci place les modules dans les repertoires correspondants, et dans l'interface de gestion des modules,
il indique que tel module est présent a tel endroit. Celui ci reçoit donc un ID dans la table indexant les modules.
 
Dans la page ou l'utilisateur veut voir apparaitre le module, il choisit dans un menu déroulant
le module qu'il veut voir executé a l'endroit ou il le souhaite.
 
Le programme principal déclare donc un objet de type module, qui executera le main() du module concerné,
apres avoir chargé le fichier de config et de fonctions, ou le fichier class.php correspondant.
 
Le probleme est que si l'utilisateur décide d'ecrire lui meme des modules, il risque de leur donner le nom de modules
existant deja. Donc, si son module et le module du meme nom sont chargés, il y a un conflit sur les noms ,  
les noms des fonctions si on est pas en POO, ou le nom des classes definissant les deux modules si on est en POO.
 
hors POO, ça donnerait :

Code :
  1. run_module($id_module)
  2. {
  3. recuperer_données_module($id_module);
  4. charger_fichier_config($id_module)
  5. charger_fichier_fonctions($id_module)
  6. executer_fonction_main_module();//lance le main du module défini dans le fichier de fonctions
  7. }


 
En POO, ça donnerait:

Code :
  1. $mod1=new Module($id_module);
  2. $mod1->executer_fonction_main_module();
  3. Module($id_module)
  4. {
  5. recuperer_données_module($id_module);
  6. charger_fichier_classe($id_module)
  7. $var=new Nom_De_La_Classe_du_Module_particulier($arguments)
  8. }


 
Ou quelquechose du genre... peut etre avec extends et de l'heritage plutot, mais bon,
en gros, voici l'idée.
 
La problematique est donc : comment etre sur que deux classes n'auront pas le meme nom, sans pour autant avoir a tenir
une liste exhaustive des classes deja crées pourr divers modules...
Il faudrait donc pouvoir déclarer dynamiquement la classe, soit en ajoutant a son nom fixe une variable (id dans la table du module, unique par définition), soit en generant son nom d'une façon quelconque garantissant son unicité.


 
L'utilisateur, il exécute pas 2 modules en même temps quand même? Donc, y'a pas de raison qu'il y ait de conflit de nom de fonction.

Reply

Marsh Posté le 17-02-2006 à 15:46:04    

sky_99 a écrit :

La problematique est donc : comment etre sur que deux classes n'auront pas le meme nom, sans pour autant avoir a tenir

SI t'en es à avoir peur de ça, alors met d'office des régles dans le nomage des classes.
Par exemple : PseudoDuDeveloppeur_NomDeSaClasse ou PseudoDuDeveloppeur_NomDeSaClasse_NumeroDeVersionMajeure
Aprés, s'il est assez couillon pour créer deux classes à lui avec le même nom, alors tant pis pour lui et arrivé à ce niveau là, il n'y a rien de plus de faisable à part si on se prend la tête pour pondre un truc lourd, difficilement débuguable et qui nécessiterait d'avoir une liste exostive de tous les modules installé.
 
PS : En plus, si tu crés dynamiquement tes classes, t'empéchera toute possibilité d'héritage car comment savoir si la référence à "maclasse" correspond à "maclasse1" ou à "maclasse2"? C'est quand même domage quand on a des modules sous forme d'objet.

Message cité 1 fois
Message édité par omega2 le 17-02-2006 à 15:48:21
Reply

Marsh Posté le 17-02-2006 à 15:50:12    

rufo a écrit :

L'utilisateur, il exécute pas 2 modules en même temps quand même? Donc, y'a pas de raison qu'il y ait de conflit de nom de fonction.

Sur mon CMS, on peut trés bien se retrouver à appeller plusieurs modules à la fois ne seraisse que quand on se logue. De plus pour le menu, chaque module posséde une fonction d'affichage d'infos dans le menu. Rien que pour créer le menu, il faut donc en charger plusieurs à la fois.
Reste à savoir si c'est pareil pour son systéme ou pas.

Reply

Marsh Posté le 17-02-2006 à 16:09:21    

ça m'a l'air d'être un peu le bazard son truc! :/

Reply

Marsh Posté le 17-02-2006 à 16:19:07    

omega2 a écrit :

SI t'en es à avoir peur de ça, alors met d'office des régles dans le nomage des classes.
Par exemple : PseudoDuDeveloppeur_NomDeSaClasse ou PseudoDuDeveloppeur_NomDeSaClasse_NumeroDeVersionMajeure
Aprés, s'il est assez couillon pour créer deux classes à lui avec le même nom, alors tant pis pour lui et arrivé à ce niveau là, il n'y a rien de plus de faisable à part si on se prend la tête pour pondre un truc lourd, difficilement débuguable et qui nécessiterait d'avoir une liste exostive de tous les modules installé.
 
PS : En plus, si tu crés dynamiquement tes classes, t'empéchera toute possibilité d'héritage car comment savoir si la référence à "maclasse" correspond à "maclasse1" ou à "maclasse2"? C'est quand même domage quand on a des modules sous forme d'objet.


 
Pour l'heritage, si on trouve une fonction comme celle qui permet de creer dyamiquement les fonctions, il y a une variable qui contient le nom de la classe... donc on pourrait avoir un truc du genre $nomclasse1 extends $nomclasse2...
Encore faut il trouver cette fonctionalité ^^
 
Le probleme ne serait pas en outre qu'il crée deux classes avec le meme nom, mais une classe ayant le meme nom qu'une autre existant deja...
 
rufo -> fais un CMS, et tu verras bien que ça n'a rien d'exeptionnel : la plupart utilisent des modules, et il est certain que tu auras plusieur modules loadés dans la meme page  :par exemple, un module "dernieres news", un modules "derniers posts du forum" et un module "sujet a la une" par exemple...
 
C'est le genre de chose qu'on trouve sur quasiement tous les sites ...
 
Je continue les recherches, mais si quelqu'un a une idée...


---------------
http://www.core-tx.com
Reply

Marsh Posté le 17-02-2006 à 16:52:52    

ben j'ai aussi un truc du genre dans un appli web. Ce sont des requêtes personnalisées (mais pas au sens SQL, ça peut renvoyer du code html, un fichier à télécharger ou un tableau paginé). Chaque user dispose de fonctions qui lui sont propres (mais elles sont partageables). C'est moi (admin/dév) qui code les requêtes. Une requête = 1 fonction nommée comme je le veux, par contre, la liste des arguments est imposée. J'ai en tout 3 fichiers php. Le premier qui sert d'ihm permet de sélectionner la requête à exécuter puis si c'est bon (le code source de la fonction existe), exécute la fonction. Le 2ième est un fichier de paramétrage : pour chaque user, je précise l'association nom de la requête/nom de la fonction php ainsi que les paramètres s'il y en a. Le dernier fichier contient le code source des fonctions. Cela dit, si ce dernier devient trop gros, je pourrais tout à fait faire un truc du genre une requête par fichier php... POur l'instant, c'est pas nécessaire.

Reply

Marsh Posté le 17-02-2006 à 21:22:36    

rufo a écrit :

ben j'ai aussi un truc du genre dans un appli web. Ce sont des requêtes personnalisées (mais pas au sens SQL, ça peut renvoyer du code html, un fichier à télécharger ou un tableau paginé). Chaque user dispose de fonctions qui lui sont propres (mais elles sont partageables). C'est moi (admin/dév) qui code les requêtes. Une requête = 1 fonction nommée comme je le veux, par contre, la liste des arguments est imposée. J'ai en tout 3 fichiers php. Le premier qui sert d'ihm permet de sélectionner la requête à exécuter puis si c'est bon (le code source de la fonction existe), exécute la fonction. Le 2ième est un fichier de paramétrage : pour chaque user, je précise l'association nom de la requête/nom de la fonction php ainsi que les paramètres s'il y en a. Le dernier fichier contient le code source des fonctions. Cela dit, si ce dernier devient trop gros, je pourrais tout à fait faire un truc du genre une requête par fichier php... POur l'instant, c'est pas nécessaire.


 
Hum... Je ne vois pas bien pourquoi tu me racontes tout ça...
Dans tous les cas, j'ai plusieur modules chargés en meme temps, chacun ayant ses propres fonctions specifiques,
etant indépendant des autres, etc.
 
Pour ma part, ça me fait plein de fichiers, des tonnes de classes par ci par la...
J'ai l'impression que tu penses que ça signifie que le tout est mal programmé... Pourtant c'est ce qu'on trouve sur beaucoup de CMS, de forums ou autres... Dans tous les cas, que ce soit mal codé ou pas, ça ne donne pas de solution absolue ;)


---------------
http://www.core-tx.com
Reply

Marsh Posté le 18-02-2006 à 12:39:19    

ben sinon, la seule solution que je vois, c'est de faire un str_replace() sur tous les noms de fonctions créées en concaténant l'id du module lors de l'enregistrement du code source du nouveau module ajouté. :/ Mais çc'est pas évident à faire...

Reply

Marsh Posté le 18-02-2006 à 16:34:11    

De toutes façons, la solution pour les fonctions a été trouvée, avec create_function, le probleme est maintenant de créer une classe dynamique ou autre... Je pense que je vais devoir faire une convention de nommage...
 
Le truc con en php, c'est qu'on ne puisse pas avoir un domaine de validité réduit pour les déclarations :s
Sinon, j'aurais mis ça dans un bloc, et basta ^^


Message édité par sky_99 le 18-02-2006 à 16:41:22

---------------
http://www.core-tx.com
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed