Clickez pour obtenir d'autres articles sur les thèmes suivant :
envoyer à un ami
Clickez ici pour envoyer ce papier à un ami (ou à un ennemi, selon votre état d'esprit).
Version imprimable
Clickez ici pour la version imprimable. Mais si vous aimez les arbres, préférez la version électronique (PDF) juste à côté...
Version PDF Amoureux de la nature, clickez-ici (ou scannez le QR code) obtenir une version PDF.
Version qrcode Scannez ce QR code pour lire cet article sur votre mobile.
Drupal, update_sql et les accolades...
le sam, 27/06/2009 - 16:34 dans Drupal
bug-buddy.png

Dans la série chercher longtemps pour trouver peu, voilà 2h que je piétinais pour comprendre pourquoi il m'était impossible de désérialiser des données stockées en base, dans la procédure de mise à jour d'un de mes module.

S'il y a bien un truc agaçant avec le système de mise à jour de Drupal, c'est cette maudite fonction update_sql. C'est en effet LA fonction préconisée pour lancer des requêtes (insert, delete, etc.) car c'est la seul qui fournisse un résultat qui pouvant être affiché dans le rapport final de mise à jour.

Alors déjà cette joyeuse fonction ne supporte pas les substitutions. Ce qui ne donne pas un code très propre. Du coup, pour insérer de la données sérialisée, on se retrouve avec des choses du genre

$serialized=serialize($mon_machin);
update_sql("insert into {ma_table} value (serialized) '".$serialized."'");
insertion d'une donnée sérialisée lors d'une mise à jour

Mais non content d'être laid, cette approche plante toute simplement. Pourquoi, à cause de l'absence de substitution, justement...

En effet, dans $serialized se trouve une chaîne de représentation sérialisée de $mon_machin. Et si l'objet d'origine contient des tableaux (ou est un tableau), PHP va insérer des accolades pour définir les différents niveaux de récursion :

a:1:{s:4:"view";a:6:{s:15:"explore_subdirs";b:0;s:17:"private_downloads";b:0;s:14:"hide_extension";b:0;s:15:
"forbidden_files";a:1:{i:0;s:0:"";}s:13:"allowed_files";a:1:
{i:0;s:0:"";}s:22:"allowed_uploaded_files";a:1:{i:0;s:0:"";}}}'
valeur serialisée

Du coup, comme update_sql n'autorise pas les substitutions, elle va passer la requêtes telle quelle à db_query qui ne s'attend pas à y trouver d'autres valeurs que %s ou %d. Ainsi, sans se poser de question, cette dernière va considérer que tout ce qui est entre accolades est un nom de table, et va tout préfixer avec le préfixe par défaut (souvent vide). Résultat des courses, une valeur sérialisée en base sans aucune accolade et donc sans espoir d'être desérialisée un jour...

Vous l'aurez compris, pour les mise à jour avec valeurs serialisées (ou risquant de contenir des accolades), update_sql c'est poubelle. Il vaut mieux ne pas avoir de rapport et utiliser le classique db_query. Là ça marche tout de suite beaucoup mieux...

Il est aussi possible de refaire proprement un update_sql de la manière suivante :

function mon_update_sql($query) {
  $args = func_get_args();
  $result = call_user_func_array("db_query", $args);
  return array('success' => $result !== FALSE, 'query' => check_plain($query));
}

Les commentaires

Maxime , le dim, 20/12/2009 - 23:27

Bonjour,

je souhaiterais mettre en place la nouvelle fonction mon_update_sql car j'ai déjà eu des problèmes de serialize() ... mais que doit-on mettre à jour et où dans notre installation Drupal pour ne plus avoir de problème ?

Publier un nouveau commentaire

Le contenu de ce champ sera maintenu privé et ne sera pas affiché publiquement. Si vous avez un compte gravatar, l'utilisez pour afficher votre avatar.
  • Les adresses de pages web et de messagerie électronique sont transformées en liens automatiquement.
  • Tags HTML autorisés : <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <br> <p> <img> <sup> <a>
  • Les lignes et les paragraphes vont à la ligne automatiquement.
  • Every instance of custom tags in the input text will be replaced with a specific tool shortcut.
  • Textual smileys will be replaced with graphical ones.

Plus d'informations sur les options de formatage