Programowe aktualizowanie pola, hook_node_update

13

Obecnie próbuje aktualizować pole za każdym razem, gdy węzeł jest tworzony lub aktualizowany. Jednak wartość nie jest wypełniana w węźle, czy mam dostęp do obiektu węzła za pomocą tego konkretnego zaczepu? Czego mogłem brakować?

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

    }
Ogólny konsensus
źródło

Odpowiedzi:

16

Opakowania metadanych jednostki

Interfejs API encji zapewnia pewne klasy opakowań, których można użyć do łatwego radzenia sobie z encjami i do wykorzystania dostarczonych modułów informacji o właściwości encji. Za pomocą opakowań można uzyskać dostęp do informacji o właściwościach, przeglądać znane właściwości lub po prostu uzyskać / ustawić opisane wartości danych itp.

Oto kilka prostych przykładów użycia, które można znaleźć w pliku README:

Aby skorzystać z tych informacji (metadanych), moduł udostępnia pewne klasy opakowań, które ułatwiają pobieranie i ustawianie wartości. Opakowanie obsługuje łańcuchowe użycie do pobierania opakowań właściwości encji, np. W celu uzyskania adresu e-mail autora węzła można użyć:

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

Aby zaktualizować adres e-mail użytkownika, można użyć

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

lub

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

Opakowania zawsze zwracają dane zgodnie z opisem w informacjach o właściwościach, które można pobrać bezpośrednio za pomocą encji_get_property_info () lub z opakowania:

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

W celu wymuszenia dezynfekcji wartości tekstowej na wyjściu można użyć np

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

aby uzyskać tytuł odkażonego węzła. Gdy właściwość jest już domyślnie zwracana w stanie odkażonym, takim jak treść węzła, prawdopodobnie chce się uzyskać niezanieczone dane, tak jak wyglądałoby to w przeglądarce dla innych przypadków użycia. W tym celu można włączyć opcję „dekodowania”, która zapewnia, że ​​wszelkie odkażone dane są usuwane, a encje HTML są dekodowane przed zwróceniem właściwości:

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

W ten sposób zawsze dostaje się dane pokazane użytkownikowi. Jeśli jednak naprawdę chcesz uzyskać surową, nieprzetworzoną wartość, nawet w przypadku oczyszczonych danych tekstowych, możesz to zrobić za pomocą:

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

Więcej przykładów:

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

Więcej dokumentów : http://drupal.org/node/1021556

retif
źródło
Dziękuję bardzo. Twoja odpowiedź pomogła mi wskazać, co musiałem zrobić. :) Społeczność kołysze !! \ m /
SGhosh
Działa to w przypadku hook_node_update, ale nie w hook_node_insert (). Otrzymasz zduplikowany błąd klucza podstawowego z mysql, ponieważ zarówno moduł węzła, jak i kod niestandardowy będą próbowały wstawić dwukrotnie ten sam węzeł (przy użyciu tego samego identyfikatora węzła).
leon.nk
14

Dzwonienie field_attach_update('node', $node)pod koniec hook_node_updatedziałało dla mnie. Zakładam, że field_attach_insert('node', $node)pod koniec też hook_node_insertbędzie działać. Przykładowa funkcja wyglądałaby następująco:

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

Nie trzeba dzwonić node_load node_saveani nic zwracać.

Myślę, że powodem tego jest fakt node_save, z którego hook_node_updatei hook_node_insertsą nazywane, okłady wszystkie zapytania do bazy danych w transakcji. (Uwaga pierwszą linię node_save: $transaction = db_transaction()). Te pytania nie są nazywane aż do node_savewykończeń. Wywoływane jest ostatnie zapytanie, które node_savedodaje się do transakcji field_attach_update, które korzysta z obiektu $ node tak jak poprzednio hook_node_update . Musisz więc ustawić kolejkę innego zapytania, dzwoniąc field_attach_updateponownie. Przynajmniej tak rozumiem, co się dzieje.

Jeśli masz problemy ze zmianą atrybutów niepolowych węzła (np. $node->log), Spróbuj także zadzwonić _node_save_revision($node, $user->uid, 'vid');. To nie utworzy nowej wersji.

grobemo
źródło
2

Oto jak zmieniasz wartości w węźle:

$node = node_load($nodeID);
$node->field_fieldname['und'][0]['value'] = $val;
node_save($node);
Lanca
źródło
4
undnie jest tu właściwie właściwe, OP stwierdził już w kodzie, że używają go $node->languagedo kodu języka
Clive
To bardzo pomocne dzięki Clive i Lance, ale chcę się upewnić, że wartość pola jest zapisywana za każdym razem, gdy węzeł jest zapisywany, stąd moje użycie hook_node_update. Czy byłoby możliwe zwrócenie $ node w tym hooku, czy też absolutnie muszę zrobić node_load? Naprawdę myślałem, że przekazałem obiekt węzła bezpośrednio przez hook_node_update ....
generalconsensus 30.01.12
Ok, więc zaktualizowałem kod zgodnie z twoją rekomendacją - jest w oryginalnej treści. Problem: Niekończąca się pętla, w której strona nie ładuje się, a zarówno mysql, jak i apache zaczynają trafiać w górę o 85% obciążenia procesora. Zdecydowanie dzieje się tutaj trochę pętli. Jakieś inne sugestie?
Konsensus ogólny
Nie mogę ci powiedzieć, co się dzieje. Ale prawdopodobnie próbujesz tylko raz załadować węzeł, wpisać coś w polu i zapisać za pomocą node_save (). Lub po prostu załaduj, wydrukuj coś (za pomocą watchdoga lub dpm () i zapisz ponownie, aby zobaczyć, czy to zadziała
Lance
Problem powstał z zapisania węzła przed jego zapisaniem, co spowodowało powstanie pętli rekurencyjnej. Zły wybór haka i słaba kompilacja
ogólny konsensus
1

Ulepszenie powyższego rozwiązania Lance'a, unikające zapisywania całego węzła, gdy modyfikowanych jest tylko kilka wartości pól:

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

Może to być również przydatne, aby uniknąć skutków ubocznych node_save().

Źródło: Zapisywanie pól węzła bez zapisywania samego węzła

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

amuli
źródło