Dotclear 2 et PHP 5.3.0
+
Par Remi le dimanche 12 avril 2009, 10:45 - HowTo - Lien permanent
llaumgui m'a fait remarqué que notre moteur de blog préféré, Dotclear 2 ne fonctionnait plus sous PHP 5.3.0 :(
J'avoue, j'avais pas testé. Mais comme je compte bientôt passer mon dédié sur la nouvelle version de PHP (probablement pour la RC2), je me suis attelé à la tâche.
Rappels :
- en PHP on ne passe pas d'argument par référence au moment de l'appel (c'est déprécié depuis un bon moment) mais c'est la fonction qui déclare attendre une référence.
- le passage par référence permet de modifier l'objet dans la fonction, mais surtout évite des copies et donc améliore les performances de l'application (consommation mémoire).
En résumé, on avait quoi :
function UneAction (&$objet) {
}
function LanceLesActions () {
call_user_func_array('UneAction', func_get_args());
}
LanceLesAction($monObjet);
L'appel de LanceLesActions provoque la copie de l'objet et donc le passage par valeur à UneAction qui attend une référence.
- En PHP ≤ 5.2.9, c'était accepté et fonctionnait, partiellement car on n'avait pas le comportement attendu, et la fonction n'avait aucune chance de pouvoir modifier le contenu de l'objet. Donc des dysfonctionnements difficiles à détecter / corriger.
- En PHP ≥ 5.3.0, c'est refusé, cela provoque un signalement, et la référence reçoit NULL au lieu d'une copie de l'objet. Donc ça ne marche plus, mais cela semble quand même plus robuste / propre.
C'est d'ailleurs écrit dans le brouillon des notes de mise à jour vers la version 5.3 : scratchpad upgrade 5.3
If a function with by-reference parameters is called by value ( for example with call_user_func_array) a warning message is produced and all by-reference parameters are set to NULL. In older versions, the function was called with by value parameters.
Quelles solutions ?
- Soit modifier toutes les fonctions de rappel pour accepter uniquement des arguments passés par valeur, mais perdre l'optimisation et provoquer un grand nombre de copies inutiles (mais c'était l'ancien fonctionnement obtenu involontairement).
function UneAction ($objet) {
}
- Soit imposer le passage par référence à LanceLesActions et perdre la souplesse de la liste d'arguments variable.
function LanceLesActions (&$objet) {
call_user_func('UneAction', $objet);
}
J'ai donc rapporté le dysfonctionnement au projet (bien entendu, comme souvent, avec une proposition de correctif) et j'attends leur retour.
A suivre..
P.S. bien sur c'est Dotclear qui est concerné ici, mais on risque de retrouver le même problème dans bon nombre d'applications.