Mise à jour d'un champ par programme, hook_node_update

13

Vous essayez actuellement de mettre à jour un champ chaque fois qu'un nœud est créé ou mis à jour. Cependant, la valeur n'est pas remplie dans le nœud, ai-je accès à l'objet nœud avec ce crochet particulier? Que pourrais-je manquer?

  function vbtoken_node_update($node) {


      entity_get_controller('node')->resetCache(array($node->nid));


      $types = node_type_get_types(); //What are the current Node Content Types?
      $yes = ($types['volunteer_project']->type);

      if($node->type === $yes){


        $hash = md5($node->title . $node->nid . $node->nid);
        $hashed = substr($hash, 0, 6);
        $node = node_load($node->nid);
        $node->tcode[$node->language][0]['value'] = $hashed;
        node_save($node);

        watchdog('vbtoken', 'Added a new Token code to %nid', array('%nid' => $node->nid));

        }
        else 
        {
          dpm('not working dude');
        }

    }
consensus général
la source

Réponses:

16

Encapsuleurs de métadonnées d'entité

L'API d'entité fournit certaines classes d'encapsuleur que vous pouvez utiliser pour traiter facilement les entités et tirer parti des modules d'informations sur les propriétés d'entité fournis. Avec l'aide des wrappers, vous pouvez accéder aux informations de propriété, parcourir les propriétés connues, ou simplement obtenir / définir les valeurs de données décrites, etc.

Voici quelques exemples d'utilisation simples que l'on trouve dans le fichier README:

Pour utiliser ces informations (métadonnées), le module fournit des classes wrapper qui facilitent l'obtention et la définition de valeurs. L'encapsuleur prend en charge l'utilisation enchaînée pour récupérer les encapsuleurs des propriétés d'entité, par exemple pour obtenir l'adresse e-mail d'un auteur de nœud que l'on pourrait utiliser:

$wrapper = entity_metadata_wrapper('node', $node);
$wrapper->author->mail->value();

Pour mettre à jour l'adresse e-mail de l'utilisateur, on pourrait utiliser

$wrapper->author->mail->set('[email protected]');

ou

$wrapper->author->mail = '[email protected]';

Les wrappers retournent toujours les données comme décrit dans les informations de propriété, qui peuvent être récupérées directement via entity_get_property_info () ou à partir du wrapper:

$mail_info = $wrapper->author->mail->info();

Afin de forcer l'obtention d'une valeur textuelle purifiée pour la sortie, on peut utiliser, par exemple

$wrapper->title->value(array('sanitize' => TRUE));

pour obtenir le titre du nœud aseptisé. Lorsqu'une propriété est déjà retournée nettoyée par défaut, comme le corps du nœud, on peut éventuellement obtenir les données non filtrées telles qu'elles apparaîtront dans un navigateur pour d'autres cas d'utilisation. Pour ce faire, on peut activer l'option «décoder», qui garantit que pour toutes les données filtrées, les balises sont supprimées et les entités HTML sont décodées avant le retour de la propriété:

$wrapper->body->value->value(array('decode' => TRUE));

De cette façon, on obtient toujours les données comme indiqué à l'utilisateur. Cependant, si vous voulez vraiment obtenir la valeur brute et non traitée, même pour les données textuelles filtrées, vous pouvez le faire via:

$wrapper->body->value->raw();

Plus d'exemples:

$wrapper->body->set(array('value' => "content"));
$wrapper->field_text[0] = 'the text';
$wrapper->field_text[0]->set(array('value' => "content"));
$wrapper->field_text2->summary = 'the summary';
$wrapper->field_text2->value = 'the text';

$wrapper->save();
$wrapper->delete();

Plus de documents : http://drupal.org/node/1021556

retif
la source
Merci beaucoup. Votre réponse m'a aidé à comprendre ce que je devais faire. :) Roches communautaires !! \ m /
SGhosh
Cela fonctionnera sur hook_node_update mais pas sur hook_node_insert (). Vous obtiendrez une erreur de clé primaire en double de mysql, car le module de nœud et votre code personnalisé essaieront d'insérer deux fois le même nœud (en utilisant le même identifiant de nœud).
leon.nk
14

Appeler field_attach_update('node', $node)à la fin de hook_node_updatetravaillé pour moi. Je suppose qu'à field_attach_insert('node', $node)la fin de ça hook_node_insertmarcherait aussi. Ainsi, un exemple de fonction ressemblerait à ceci:

function mymodule_node_update($node) {
  $new_value = // ...do some stuff to compute a new value for the field.
  $node->field_my_field[LANGUAGE_NONE][0]['value'] = $new_value;
  field_attach_update('node', $node);
}

Il n'est pas nécessaire d'appeler node_load node_saveou de retourner quoi que ce soit.

Je pense que la raison en est que node_save, à partir de laquelle hook_node_updateet hook_node_insertsont appelés, encapsule toutes les requêtes de base de données dans une transaction. (Notez la première ligne node_save: $transaction = db_transaction().) Ces requêtes ne sont pas appelées jusqu'à node_savefinitions. La dernière requête qui node_saves'ajoute à la transaction est appelée à partir de field_attach_update, qui utilise l'objet $ node tel qu'il est avant hook_node_update est appelé. Vous devez donc mettre en file d'attente une autre requête en appelant à field_attach_updatenouveau. C'est du moins ce que je comprends de ce qui se passe.

Si vous rencontrez des problèmes pour modifier les attributs non liés au champ du nœud (par exemple, $node->log), essayez _node_save_revision($node, $user->uid, 'vid');également d' appeler . Cela ne créera pas de nouvelle révision.

grobemo
la source
2

Voici comment vous modifiez les valeurs sur un nœud:

$node = node_load($nodeID);
$node->field_fieldname['und'][0]['value'] = $val;
node_save($node);
Lance
la source
4
undn'est pas vraiment approprié ici, OP a déjà déclaré dans le code qu'ils utilisent $node->languagepour le code de langue
Clive
C'est super utile, merci Clive et Lance, mais je veux m'assurer que la valeur du champ est enregistrée chaque fois que le nœud est enregistré, d'où mon utilisation de hook_node_update. Serait-il possible de retourner le nœud $ dans ce hook ou dois-je absolument faire un nœud_load? Je pensais vraiment avoir fait passer l'objet nœud directement via hook_node_update ....
generalconsensus
Ok donc j'ai mis à jour le code selon votre recommandation - il est dans le corps d'origine. Problème: boucle sans fin dans laquelle la page ne se charge pas et mysql et apache commencent à atteindre plus de 85% de charge sur le processeur. Il y a certainement une boucle en cours ici. D'autres suggestions?
consensus général
Je ne peux pas vous dire ce qui se passe. Mais vous essayez probablement une fois de charger le nœud, d'entrer quelque chose dans le champ et de l'enregistrer en utilisant node_save (). Ou chargez, imprimez quelque chose (en utilisant watchdog ou dpm () et enregistrez-le à nouveau pour voir si cela fonctionne.
Lance
Le problème provenait de l'enregistrement du nœud avant de l'enregistrer, ce qui entraînait une boucle récursive. Mauvais choix de crochets et mauvaise construction
consensus général
1

Une amélioration de la solution de Lance ci-dessus, évitant la sauvegarde d'un nœud entier lorsque seules quelques valeurs de champ sont modifiées:

$node = node_load($nodeID);
// for each field whose value remains unchanged
unset($node->field_<field-name>); 
// for each field whose value changes
$node->field_<field-name>[LANGUAGE_NONE][0]['value'] = <new-value>;
field_attach_update('node', $node);
entity_get_controller('node')->resetCache(array($node->nid));

Cela pourrait également être utile pour éviter les effets secondaires de node_save().

Source: enregistrement des champs du nœud sans enregistrer le nœud lui-même

https://www.urbaninsight.com/2011/10/24/saving-nodes-fields-without-saving-node-itself

amuli
la source