Programmgesteuertes Aktualisieren eines Felds, hook_node_update

13

Derzeit wird versucht, ein Feld jedes Mal zu aktualisieren, wenn ein Knoten erstellt oder aktualisiert wird. Der Wert wird jedoch nicht im Knoten ausgefüllt. Habe ich mit diesem bestimmten Hook Zugriff auf das Knotenobjekt? Was könnte mir fehlen?

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

    }
allgemeiner Konsens
quelle

Antworten:

16

Wrapper für Entitätsmetadaten

Die Entitäts-API bietet einige Wrapper-Klassen, mit denen Sie auf einfache Weise mit Entitäten umgehen und die bereitgestellten Entitätseigenschafts-Informationsmodule nutzen können. Mit Hilfe der Wrapper können Sie auf die Eigenschaftsinformationen zugreifen, bekannte Eigenschaften durchlaufen oder einfach die beschriebenen Datenwerte abrufen / festlegen usw.

Dies sind einige einfache Anwendungsbeispiele, wie sie in der README zu finden sind:

Um diese Informationen (Metadaten) zu nutzen, stellt das Modul einige Wrapper-Klassen zur Verfügung, die das Abrufen und Festlegen von Werten erleichtern. Der Wrapper unterstützt die verkettete Verwendung zum Abrufen von Wrappern von Entitätseigenschaften, z. B. um die E-Mail-Adresse eines Knotenautors abzurufen, die verwendet werden kann:

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

Um die E-Mail-Adresse des Benutzers zu aktualisieren, könnte man verwenden

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

oder

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

Die Wrapper geben die Daten immer wie in den Eigenschaftsinformationen beschrieben zurück, die direkt über entity_get_property_info () oder vom Wrapper abgerufen werden können:

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

Um zu erzwingen, dass ein Textwert für die Ausgabe bereinigt wird, kann man z

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

um den Titel des bereinigten Knotens zu erhalten. Wenn eine Eigenschaft wie der Knotenkörper bereits standardmäßig bereinigt zurückgegeben wird, möchten Sie möglicherweise die nicht bereinigten Daten abrufen, wie sie in einem Browser für andere Anwendungsfälle angezeigt würden. Dazu kann die Option 'decode' aktiviert werden, mit der sichergestellt wird, dass die Tags für bereinigte Daten entfernt und HTML-Entitäten dekodiert werden, bevor die Eigenschaft zurückgegeben wird:

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

Auf diese Weise erhält man die Daten immer so, wie sie dem Benutzer angezeigt werden. Wenn Sie jedoch den unverarbeiteten Rohwert auch für bereinigte Textdaten erhalten möchten, können Sie dies über Folgendes tun:

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

Mehr Beispiele:

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

Weitere Dokumente : http://drupal.org/node/1021556

retif
quelle
Ich danke dir sehr. Ihre Antwort hat mir geholfen, eine Richtung für das zu geben, was ich tun musste. :) Community rockt !! \ m /
SGhosh
Dies funktioniert bei hook_node_update, aber nicht bei hook_node_insert (). Sie erhalten einen doppelten Primärschlüsselfehler von mysql, da sowohl das Knotenmodul als auch Ihr benutzerdefinierter Code versuchen, denselben Knoten zweimal einzufügen (mit derselben Knoten-ID).
leon.nk
14

Anruf field_attach_update('node', $node)am Ende hook_node_updatehat bei mir geklappt. Ich gehe davon aus, dass field_attach_insert('node', $node)am Ende hook_node_insertauch funktionieren würde. Eine Beispielfunktion würde also so aussehen:

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

Sie müssen nicht anrufen node_load node_save nichts oder zurückgeben.

Ich denke, der Grund dafür ist, dass node_save, von dem aus hook_node_updateund hook_node_insertaufgerufen werden, alle Datenbankabfragen in eine Transaktion eingeschlossen werden. (Beachten Sie die erste Zeile von node_save:. $transaction = db_transaction()) Diese Abfragen werden erst nach Abschluss aufgerufen node_save. Die letzte Abfrage, node_savedie der Transaktion hinzugefügt wird field_attach_update, wird von aufgerufen. Dabei wird das $ node-Objekt wie zuvor hook_node_update aufgerufen. Sie müssen also eine weitere Abfrage in die Warteschlange stellen, indem Sie anrufenfield_attach_update erneut . Zumindest verstehe ich das so.

Wenn Sie Probleme beim Ändern von Nichtfeldattributen des Knotens haben (z. B. $node->log), rufen Sie _node_save_revision($node, $user->uid, 'vid');ebenfalls an. Dadurch wird keine neue Revision erstellt.

grobemo
quelle
2

So ändern Sie Werte auf einem Knoten:

$node = node_load($nodeID);
$node->field_fieldname['und'][0]['value'] = $val;
node_save($node);
Lanze
quelle
4
undist hier nicht wirklich angebracht, OP hat bereits im Code angegeben, dass sie $node->languagefür den Sprachcode verwenden
Clive
Das ist super hilfreich, danke Clive und Lance, aber ich möchte sicherstellen, dass der Feldwert immer gespeichert wird, wenn der Knoten gespeichert wird, daher verwende ich hook_node_update. Wäre es möglich, den $ -Knoten in diesem Hook zurückzugeben, oder muss ich unbedingt eine node_load ausführen? Ich dachte wirklich, ich hätte das Node-Objekt direkt durch hook_node_update übergeben ...
Generalconsensus
Ok, also habe ich den Code gemäß Ihrer Empfehlung aktualisiert - er befindet sich im Originalkörper. Problem: Endlosschleife, in der die Seite nicht geladen wird und sowohl MySQL als auch Apache ab einer CPU-Auslastung von 85% starten. Hier ist definitiv eine Schleife im Gange. Irgendwelche anderen Vorschläge?
Generalkonsens
Ich kann dir nicht sagen, was los ist. Aber wahrscheinlich versuchen Sie einmal, den Knoten zu laden, etwas in das Feld einzugeben und es mit node_save () zu speichern. Oder einfach laden, etwas drucken (mit Watchdog oder dpm ()) und es erneut speichern, um zu sehen, ob dies funktioniert.
Lance
Das Problem wurde dadurch verursacht, dass der Knoten vor dem Speichern gespeichert wurde, was zu einer rekursiven Schleife führte. Schlechte Hook-Auswahl und schlechte Figur
allgemeiner
1

Eine Verbesserung der obigen Lance-Lösung, bei der das Speichern eines gesamten Knotens vermieden wird, wenn nur wenige Feldwerte geändert werden:

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

Dies könnte auch nützlich sein, um Nebenwirkungen von zu vermeiden node_save().

Quelle: Speichern der Felder des Knotens, ohne den Knoten selbst zu speichern

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

Amuli
quelle