Aggiornamento di un campo a livello di codice, hook_node_update


13

Attualmente sto cercando di aggiornare un campo ogni volta che un nodo viene creato o aggiornato. Tuttavia, il valore non viene popolato all'interno del nodo, posso accedere all'oggetto nodo con questo hook particolare? Cosa potrei perdere?

  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');
        }

    }

Risposte:


16

Wrapper di metadati di entità

L'API di entità fornisce alcune classi di wrapper che è possibile utilizzare per gestire facilmente le entità e sfruttare i moduli di informazioni sulla proprietà delle entità forniti. Con l'aiuto dei wrapper è possibile accedere alle informazioni sulle proprietà, passare in rassegna le proprietà note o semplicemente ottenere / impostare i valori dei dati descritti, ecc.

Questi sono alcuni semplici esempi di utilizzo che si trovano nel file README:

Per utilizzare queste informazioni (metadati) il modulo fornisce alcune classi wrapper che facilitano il recupero e l'impostazione dei valori. Il wrapper supporta l'utilizzo concatenato per il recupero di wrapper delle proprietà dell'entità, ad esempio per ottenere l'indirizzo di posta dell'autore di un nodo che è possibile utilizzare:

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

Per aggiornare l'indirizzo di posta dell'utente è possibile utilizzare

$wrapper->author->mail->set('sepp@example.com');

o

$wrapper->author->mail = 'sepp@example.com';

I wrapper restituiscono sempre i dati come descritto nelle informazioni sulla proprietà, che possono essere recuperati direttamente tramite entity_get_property_info () o dal wrapper:

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

Per forzare l'ottenimento di un valore testuale disinfettato per l'output è possibile utilizzare, ad es

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

per ottenere il titolo del nodo sanificato. Quando una proprietà viene già restituita sterilizzata per impostazione predefinita, come il corpo del nodo, è possibile che si desideri ottenere i dati non disinfettati come apparirebbero in un browser per altri casi d'uso. Per fare ciò è possibile abilitare l'opzione 'decodifica', che assicura che per ogni dato sanificato i tag vengano rimossi e le entità HTML vengano decodificate prima che la proprietà venga restituita:

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

In questo modo si ottengono sempre i dati mostrati all'utente. Tuttavia, se vuoi davvero ottenere il valore grezzo, non elaborato, anche per i dati testuali disinfettati, puoi farlo tramite:

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

Altri esempi:

$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();

Altri documenti : http://drupal.org/node/1021556


Grazie mille. La tua risposta mi ha aiutato a orientarmi verso ciò che dovevo fare. :) Rock della comunità !! \ m /
SGhosh,

Questo funzionerà su hook_node_update ma non su hook_node_insert (). Otterrai un errore di chiave primaria duplicato da mysql, poiché sia ​​il modulo del nodo che il tuo codice personalizzato tenteranno di inserire due volte lo stesso nodo (utilizzando lo stesso ID nodo).
leon.nk,

14

Chiamare field_attach_update('node', $node)alla fine ha hook_node_updatefunzionato per me. Presumo che field_attach_insert('node', $node)alla fine hook_node_insertfunzionerebbe anche. Quindi, una funzione di esempio sarebbe simile a questa:

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);
}

Non è necessario chiamare node_load node_saveo restituire nulla.

Penso che la ragione di ciò sia che node_save, da cui hook_node_updatee hook_node_insertsono chiamati, racchiude tutte le query del database in una transazione. (Nota la prima riga di node_save:. $transaction = db_transaction()) Queste query non vengono chiamate fino al node_savetermine. node_saveViene richiamata l'ultima query che si aggiunge alla transazione field_attach_update, che utilizza l'oggetto $ node com'era prima hook_node_update . Quindi è necessario mettere in coda un'altra query chiamando di field_attach_updatenuovo. Almeno, questa è la mia comprensione di ciò che sta succedendo.

Se hai problemi a modificare gli attributi non di campo del nodo (ad esempio, $node->log), prova _node_save_revision($node, $user->uid, 'vid');anche a chiamare . Questo non creerà una nuova revisione.


2

Ecco come si modificano i valori su un nodo:

$node = node_load($nodeID);
$node->field_fieldname['und'][0]['value'] = $val;
node_save($node);

4
undnon è davvero appropriato qui, OP ha già dichiarato nel codice che stanno usando $node->languageper il codice lingua
Clive

Questo è molto utile grazie a Clive e Lance, ma voglio assicurarmi che il valore del campo venga salvato ogni volta che il nodo viene salvato, quindi il mio uso di hook_node_update. Sarebbe possibile restituire $ node in questo hook o devo assolutamente fare un node_load? Ho davvero pensato che avevo l'oggetto nodo passato direttamente attraverso hook_node_update ....
generalconsensus

Ok, quindi ho aggiornato il codice secondo la tua raccomandazione - è nel corpo originale. Problema: ciclo infinito in cui la pagina non viene caricata e sia mysql che apache iniziano a colpire verso l'alto con un carico dell'85% su CPU. Sicuramente ci sono alcuni loop in corso qui. Altri suggerimenti?
consenso generale

Non posso dirti cosa sta succedendo. Ma probabilmente provi una volta solo a caricare il nodo, inserire qualcosa nel campo e salvarlo usando node_save (). O semplicemente carica, stampa qualcosa (usando watchdog o dpm () e salvalo di nuovo per vedere se funziona.
Lance

Il problema è derivato dall'aver salvato il nodo prima di salvarlo con conseguente ciclo ricorsivo. Scarsa scelta del gancio e scarsa costruzione
consenso generale

1

Un miglioramento della soluzione di Lance sopra, evitando il salvataggio di un intero nodo quando vengono modificati solo alcuni valori di campo:

$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));

Questo potrebbe anche essere utile per evitare effetti collaterali di node_save().

Origine: salvataggio dei campi del nodo senza salvare il nodo stesso

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.