migration vers CF9 - à quoi faire attention dans son code

Vous vous posez des questions sur la configuration requise ou rencontrez un souci lors de l'installation, vous êtes dans la bonne rubrique.

migration vers CF9 - à quoi faire attention dans son code

Messagede olivierb le Mer 09 Déc 2009 16:14

Je suggère l'ouverture d'un post pour éventuellement regrouper les petites surprises et imprévus liés au passage à CF9. genre code incompatible, ... n'hésitez pas à poster vos petites histoires...

J'ouvre le bal avec 2 trucs un peu tarabiscotés qui ne vous impacteront peut-être pas mais que j'ai envie de conserver histoire de potentiellement éviter de l'arrachage de cheveux à d'autres personnes.

- isdefined("") et cfoutput
Test classique :
  1. <cfif i eq 2>
  2. <cfset toto = mafonction() />
  3. </cfif>
  4. <cfif isdefined("toto")><cfoutput>#toto#</cfoutput></cfif>


Dans le cas où mafonction() est censée retourner une chaine (returntype "string" dans le cffunction) mais qu'on a fait un "cfreturn" sans rien derrrière (par exemple dans le cas d'un "else") alors :
- En CF8 aucun message d'erreur mais le <cfset toto = ...> ne créait pas la variable toto
donc le isdefined("toto")> retournait false
- En CF9 aucun message d'erreur non plus pour le cfset, mais la variable toto est bien créée MAIS avec une valeur "undefined"
donc le test isdefined("toto") renvoie TRUE (on rentre dans le cfif) mais le cfoutput de #toto# est invalide et fait crasher la page car la valeur est undefined (et n'est donc pas une string)

Ca se corrige assez facilement en s'assurant que le retour de la fonction est bien une chaine (même vide genre cfreturn "") et non pas une valeur non définie. (On pourrait penser que ça aurait dû faire planter CF à ce niveau car <cfreturn /> ne retourne pas une chaine alors que le returntype requis est justement une chaine, mais CF ne réagit pas à ce moment là)

2è découverte : le composant cfx_excel2query ne fonctionne plus sous CF9. Je pense qu'il s'agit de la même problématique que d'habitude (je l'avais eu avec l'introduction de cfimage); à savoir qu'Adobe reprend les librairies classiques de Java pour faire ses nouveaux tags (cfspreadsheet est probablement basé sur POI en l'occurence). du coup on ne peut plus appeler POI comme on le faisait avant.

Solution : en attendant une suggestion de Ryan Emerle http://www.emerle.net (le créateur du tag) le plus simple reste d'adapter son code pour utiliser les nouvelles balises de CF.

Bon par contre (allez savoir pourquoi) le composant qui fait l'inverse (cfx_query2Excel) lui continue à fonctionner et c'est bien cool parce que c'est le truc le plus chiant à adapter (notamment l'ajout de données sur un template xls existant qui est super simple avec le cfx et a l'air plus pénible avec la fonction de CF)
olivierb
 
Messages: 62
Inscription: Lun 27 Avr 2009 17:51

Re: migration vers CF9 - à quoi faire attention dans son code

Messagede olivierb le Ven 11 Déc 2009 10:51

Nouvelle surprise du jour (en pratique c'est plutôt une révélation de nos propres erreurs de code qui passaient auparavant sans souci dans les versions précédentes)
Imaginons une fonction à laquelle on passe comme argument une liste de fichiers.
Cette fonction écrit un fichier contenant cette liste de fichiers avec un en-tête au début du fichier (et 1 fichier par ligne)
<cffunction name="ecritlefichier" output="true">
<cfargument name="fichiers">
<cfsavecontent variable="fichiers">"blablah d'en-tête"
"\"
<cfloop index="fichier" list="#fichiers#">
#fichier#
</cfloop>
</cfsavecontent>
<cffile action="write" file="liste.txt" output="#fichiers#">
</cffunction>

Petite boulette : l'argument passé à la fonction est le même que la variable locale définie par le cfsavecontent (pas futé de ma part mais des fois on ne s'en rend pas compte.

CF8 : la variable locale primait, et c'est donc elle qui était utilisée pour le write
CF9 : c'est la variable d'argument de la fonction qui prime donc dans mon fichier il n'y a au final que la liste des fichiers (argument de la fonction)

C'était prévu que CF9 soit plus strict que les versions précédentes, mais là on a un changement de comportement auquel il faut faire gaffe.
On utilise parfois des choses plus triviales du genre écrasement volontaire de la variable d'argument de la fonction par exemple <cfset fichiers = replace(fichiers,"'","","all") /> pour virer des quotes ou qqch du genre... si on fait ça et qu'on utilise fichiers"" un peu plus loin en pratique la liste pourra toujours contenir des quotes :-(
A surveiller !
olivierb
 
Messages: 62
Inscription: Lun 27 Avr 2009 17:51

Re: migration vers CF9 - à quoi faire attention dans son code

Messagede eric00000007 le Ven 18 Déc 2009 01:37

pas futé de ma part mais des fois on ne s'en rend pas compte

Aie ! il doit y avoir pas mal de boulettes dans plein de scripts. Ca me fait un peu peur cette histoire mais je vais essayer de pister cela. Ca ne va pas être facile. Il y a 5 ans je ne pointais pas trop les variables :-(
eric00000007
 
Messages: 426
Inscription: Mer 31 Oct 2007 10:55
Localisation: Paris

Re: migration vers CF9 - à quoi faire attention dans son code

Messagede olivierb le Mer 23 Déc 2009 12:03

Nouveau cas concrêt de problème avec les booléens/non définis :

  1. <cfset termine = Application.memcached.get("newsletter:envoi:termine")>
  2. <cif termine eq 0>
  3.  blablabla
  4. </cfif>


Je récupère de memcached une valeur (l'info que mon envoi de newsletters est terminé).
globalement il peut y avoir 3 retours retournées par memcached :
- RIEN : dans le cas où la variable n'est pas dans le cache
- 0 : l'envoi est en cours (terminé faux)
- 1 : l'envoi est terminé

Avec CF8 il y avait bien une distinction nette des 3 cas, le teste "termine eq 0" étant validé uniquement lorsqu'on récupérait bien une valeur égale à 0 de memcached

Avec CF9, RIEN est confondu avec 0. Si je ne récupère rien de memcached (car la valeur n'est pas en cache) alors on rentre dans le if.

Solution 'bidouille' : rajouter un "AND len(termine) eq 1" dans le test... la longueur de la valeur RIEN étant 5 (false) !
olivierb
 
Messages: 62
Inscription: Lun 27 Avr 2009 17:51

ORA-00911 invalid caracter

Messagede Marc le Jeu 01 Avr 2010 13:05

J'ai migré de CF4.5 vers CF9 ...

Tout se passe relativement bien à l'exception de l'erreur Oracle reprise dans mon titre.
Après quelques recherches et plusieurs tests il s'avère que l'erreur survient quand je met un ";" à la fin d'une instruction sql dans un cfquery!
Si je supprime mes ";" ca passe sans problème ... Quelqu'un a une idée pour m'éviter de supprimer tous les ";" dans tous les query de toutes mes pages ? :)?
Marc
 
Messages: 132
Inscription: Mar 16 Oct 2007 08:57
Localisation: Brussels

Re: migration vers CF9 - à quoi faire attention dans son code

Messagede eric00000007 le Ven 27 Aoû 2010 11:44

Requêtes avec des queryparam en commentaire sous MySQL
Exemple
  1.  
  2. <cfquery name="updateUser" datasource="#mydatasource#"
  3. UPDATE users
  4. SET
  5. date_updated = NOW() ,
  6. -- username = <cfqueryparam cfsqltype="cf_sql_longvarchar" value="#form.username#">
  7. first_name = <cfqueryparam cfsqltype="cf_sql_longvarchar" value="#form.first_name#">
  8.  WHERE id = <cfqueryparam cfsqltype="cf_sql_integer" value="#session.id#">
  9. </cfquery>

Erreur retourcé par CF9
Error Executing Database Query.
Parameter index out of range (3 > number of parameters, which is 2).


Solution
Mettre en commentaire CF ou bien suprimer la ligne avec le commentaire SQL et le cfqueryparam. Et pour une bonne pratique, ne pas laisser de commentaires inutiles.
  1.  
  2. <cfquery name="updateUser" datasource="#mydatasource#"
  3. UPDATE users
  4. SET
  5. date_updated = NOW() ,
  6. <!-- username= <cfqueryparam cfsqltype="cf_sql_longvarchar" value="#form.username#">
  7. --->
  8. first_name = <cfqueryparam cfsqltype="cf_sql_longvarchar" value="#form.first_name#">
  9.  WHERE id = <cfqueryparam cfsqltype="cf_sql_integer" value="#session.id#">
  10. </cfquery>
eric00000007
 
Messages: 426
Inscription: Mer 31 Oct 2007 10:55
Localisation: Paris


Retourner vers Installation

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 1 invité

cron