[Résolu] Hook Post Update Drupal 7 ?

Information importante

En raison d'un grand nombre d'inscriptions de spammers sur notre site, polluant sans relache notre forum, nous suspendons la création de compte via le formulaire de "sign up".

Il est néanmoins toujours possible de devenir adhérent•e en faisant la demande sur cette page, rubrique "Inscription" : https://www.drupal.fr/contact


De plus, le forum est désormais "interdit en écriture". Il n'est plus autorisé d'y écrire un sujet/billet/commentaire.

Pour contacter la communauté, merci de rejoindre le slack "drupalfrance".

Si vous voulez contacter le bureau de l'association, utilisez le formulaire disponible ici, ou envoyez-nous un DM sur twitter.

Hey all,

J'ai un souci au niveau d'un hook update (je suis un noob en drupal)
Je souhaite après update, insertion ou suppression d'un field node générer un fichier XML lui-même lu dans un flash.

J'ai donc créé un module dans lequel je hook, par exemple ici sur un update :
(J'ai testé avec plusieurs hooks : node_update, entity_update etc..)

function aa_field_attach_update($entity_type, $entity) {
if ($entity_type=="node" && $entity->type=="fm") {
      //error_log ("UPDATE FM");
       majXML();
  }
}

Et ma fonction majXML() où je load mes contenus pour écrire dans un fichier xml :

function majXML(){
        $xml = "";
        $conditions = Array ("type" => "fm");
        $entity = entity_load('node', FALSE, $conditions, FALSE);

        foreach($entity as $value)  {
            $xml.= '<exemple id="'.$value->nid.'"/>';
        }
      
        // Puis écriture dans le XML etc..
}

Mon problème, c'est que l'entity_load me charge les données pre-update et non post-update du node que je viens de modifier.

J'ai réglé le souci temporairement par un bricolage en passant à la fonction majXML l'entité en cours de modif : majXML($entity, "update");

A noter que je retombe sur le même souci avec le delete mais pas l'insert.

Néanmoins, si je lis la documentation, cela devrait être un hook après update des données.

C'est pourquoi je recherche un moyen plus propre de réaliser le traitement, d'où mes questions :

  • Est-ce un souci au niveau des tables de cache ?
  • Y a t-il un autre hook utilisable et exécuté "plus tard" afin de s'assurer que les données soient à jour ?
  • Une suggestion ?

Merci de votre aide ^o^

Forum : 
Version de Drupal : 

Les fonctions liées aux entités ne sont pas vraiment finalisées, donc je me demande si c'est une bonne idée de s'appuyer dessus pour le moment.

Surtout que pour ce cas, tu gères des nodes 'normales', donc tu devrais pouvoir t'en sortir avec les hooks les concernant. Tu as essayé celui-là http://api.drupal.org/api/drupal/modules--node--node.api.php/function/ho... ?

Il y a tout un tas de suggestions pour faire diverses choses là http://api.drupal.org/api/drupal/modules--node--node.api.php/group/node_...

Merci pour ta réponse Numerizen :)

Pour le presave, il est dit : This hook is invoked from node_save() before the node is saved to the database.

Il me faudrait en fait le postsave en quelque sorte, ce qui doit correspondre à l'update imo.

En fait, j'ai essayé une multitude de hooks parmi la liste donnée sans jamais avoir trouvé le bon. Je me demande si c'est pas plutôt l'entity_load que je dois remplacer ?

Je viens de tester avec node_load_multiple, mais c'est kiffkiff T-T

Anyway, merci pour le conseil sur les entities, je ferai attention.

J'ai testé en vidant toutes les tables de cache mais rien n'y fait.
En fait, les commentaires sur la doc du hook_node_update sont clairs :
http://api.drupal.org/api/drupal/modules--node--node.api.php/function/ho...

Don't be fooled

Into reading the above and thinking that your node has already been saved. I ran into a situation where I was doing a node_load on the nid of the passed node, which would provide me with the OLD values - the ones that should have been replaced before this hook was invoked.

<?php
function hook_node_update($node) {
    
// Provides the "updated" values
    
dpm($node);

    
$loaded_node = node_load($node->nid);
    
// Provides the old values, which shouldn't be there according
     // to the documentation above
    
dpm($loaded_node);
}
?>

Dans ce cas, je vais rester dans mon fonctionnement actuel, faute de trouver une solution plus propre, à savoir passer à la fonction le node à jour, et faire un traitement spécifique pour l'exclure du load général afin d'obtenir toutes les versions des nodes souhaitées.

Merci pour l'aide.
See ya !

Je vais mettre ma solution en simplifiant avec juste le cas de l'update, ça peut toujours aider :

<?php
function majXML($fiche) {

  
$data = Array();
  
$conditions = Array ("type" => "fm");
  
$entity = entity_load('node', FALSE, $conditions, FALSE);

   foreach(
$entity as $value)  {
      
     
// Si nid node = nid fiche alors on prend les datas de la fiche passée en param
       
if ($value->nid == $fiche->nid ) {
          
$data[]=$fiche->myfield;
        }
     
// Sinon on utilise les données en base
       
else {
        
$data[]=$value->myfield;
        }
  }

 
// FOPEN/FWRITE/FCLOSE XML à partir de $data

}

// Hook sur update fields

function aa_field_attach_update($entity_type, $entity) {
   if (
$entity_type=="node" && $entity->type=="fm") {
     
//error_log ("UPDATE FM");
      
majXML($entity);
   }
}
?>

Une dernière note pour conclure et pour dire qu'en fait le comportement décrit plus haut est souhaitable.

Je m'explique : je dois lancer des notifications mails lorsque une actualité est publiée, c'est à dire :

  • Lorsque node_insert et que node->status = 1
  • Lorsque node_update et que old_node->status = 0 && new_node->status = 1

Cela permet donc d'obtenir un état avant/après que je ne peux catcher autrement.

Vous pouvez donc tagger ce thread à [Résolu] (je ne crois pas pouvoir le faire vu que je ne peux pas accepter ma propre réponse :D)

Les entitiés chargées sont mise en cache en mémoire. Ce cache est remis à zero après un node_save(), mais seulement à la toute fin du processus.

Dans votre cas, le plus simple est d'appeller entity_load() avec le paramètre $reset à TRUE:

<?php
$conditions
= array('type' => 'fm');
$entities = entity_load('node', FALSE, $conditions, TRUE);

$xml = '';
foreach (
$entities as $value)  {
 
$xml .= '<exemple id="' . $value->nid . '"/>';
}
?>

D'autres remarques en vrac:

  • votre code ne satisfait pas aux conventions de code de Drupal,
  • si vous ne cherchez qu'à trouver les IDs d'entité vous pouvez utiliser EntityFieldQuery ce qui évite l'opération de chargement,
  • vous pouvez utilement utiliser SimpleXML pour générer du XML ce qui vous évitera d'avoir à encoder les différentes valeurs et attributs,
  • le résultat d'un entity_load() est un tableau d'entités, le nom de la variable doit donc être pluriel,
  • les fonctions liées aux entitiés sont bien finalisées contrairement à ce qu'indique la première réponse à ce thread.

J'essaierai d'appliquer vos pistes dés demain et je ferai un retour sur les modifications.
J'utilise effectivement SimpleXML, c'était pour simplifier l'exemple ^^

Votre avis m'intéresse en ce qui concerne mon dernier commentaire sur les actualités.
Est-il propre de procéder comme tel pour vérifier une valeur avant et après update ?

Merci pour les remarques très constructives !

les fonctions liées aux entitiés sont bien finalisées contrairement à ce qu’indique la première réponse à ce thread.

Bon à savoir ça. Ma remarque m'est venue parce que j'ai lu pas mal de choses, entre autres sur le système i18n et Entity Translation qui montraient que l'intégration des entités n'était pas stable partout.

Il est vrai que je n'aurais pas dû en conclure quoi que ce soit sur les fonctions de base.

Ceci dit, le problème peut être solutionné avec node_load et le même argument $reset, non ? Je m'en veux d'ailleurs de ne pas y avoir pensé avant dans ce thread.

D'une façon générale, j'hésite encore à me servir des entités, qui ne me semble se justifier que pour les cas où les nodes ne font pas le job, cas que je n'ai pas encore rencontré depuis D7.

L'avis d'un core developper sur la question m'intéresse au plus haut point.

En fait, je cherche à récupérer la valeur d'un field personnalisé.
Même après vidage de cache, je n'obtiens pas les bonnes valeurs.
Je pense que je n'utilise pas les bons hooks, mon traitement semble être effectué "trop tôt"
Existe t-il un hook que l'on peut utiliser après save ?

C'est bon !!

En utilisant le hook node_update à la place du hook field_attach_update
Le 1er est postérieur au 2e.

Et effectivement le $reset à TRUE

<?php
$entities
= entity_load('node', FALSE, $conditions, TRUE);
?>

Merci beaucoup à vous deux ^o^
Je vais voir maintenant le coup du $entity->original !

Bonne journée à vous, je sens qu'on va se recroiser :D

Et merci aussi pour la solution sur l'avant/après qui fonctionne parfaitement et me permet de savoir si un contenu a été publié !
NEW VALUE : $entity->status
OLD VALUE : $entity->original->status