Memperbarui bidang secara pemrograman, hook_node_update


13

Saat ini mencoba memperbarui bidang setiap kali sebuah node dibuat atau diperbarui. Namun nilainya tidak diisi dalam node, apakah saya memiliki akses ke objek node dengan kait khusus ini? Apa yang bisa saya lewatkan?

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

    }

Jawaban:


16

Pembungkus metadata entitas

API entitas menyediakan beberapa kelas wrapper yang dapat Anda gunakan untuk menangani entitas dengan mudah dan untuk meningkatkan modul informasi properti entitas yang disediakan. Dengan bantuan pembungkus Anda dapat mengakses informasi properti, mengulangi properti yang diketahui, atau hanya mendapatkan / mengatur nilai data yang dijelaskan, dll.

Ini adalah beberapa contoh penggunaan sederhana seperti yang ditemukan dalam README:

Untuk memanfaatkan informasi ini (metadata) modul menyediakan beberapa kelas pembungkus yang memudahkan untuk mendapatkan dan menetapkan nilai. Wrapper mendukung penggunaan berantai untuk mengambil pembungkus properti entitas, misalnya untuk mendapatkan alamat email pembuat simpul yang bisa digunakan:

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

Untuk memperbarui alamat email pengguna, seseorang dapat menggunakan

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

atau

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

Pembungkus selalu mengembalikan data seperti yang dijelaskan dalam informasi properti, yang dapat diambil langsung melalui entity_get_property_info () atau dari pembungkus:

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

Untuk memaksa mendapatkan nilai tekstual yang disanitasi untuk output yang dapat digunakan, misalnya

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

untuk mendapatkan judul simpul yang disanitasi. Ketika sebuah properti sudah kembali disterilkan secara default, seperti badan simpul, seseorang mungkin ingin mendapatkan data yang tidak dibersihkan seperti yang akan muncul di browser untuk kasus penggunaan lainnya. Untuk melakukannya, seseorang dapat mengaktifkan opsi 'decode', yang memastikan untuk setiap data yang disanitasi, tag-tag dilucuti dan entitas HTML di-decode sebelum properti dikembalikan:

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

Dengan begitu orang selalu mendapatkan data seperti yang ditunjukkan kepada pengguna. Namun, jika Anda benar-benar ingin mendapatkan nilai mentah, tidak diproses, bahkan untuk data tekstual yang sudah disanitasi, Anda dapat melakukannya melalui:

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

Lebih banyak contoh:

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

Lebih banyak dokumen : http://drupal.org/node/1021556


Terima kasih banyak. Jawaban Anda membantu memberi saya arahan tentang apa yang harus saya lakukan. :) Komunitas batu !! \ m /
SGhosh

Ini akan bekerja pada hook_node_update tetapi tidak pada hook_node_insert (). Anda akan mendapatkan kesalahan kunci primer duplikat dari mysql, karena modul simpul dan kode kustom Anda akan mencoba memasukkan simpul yang sama dua kali (menggunakan id simpul yang sama).
leon.nk

14

Memanggil field_attach_update('node', $node)di akhir hook_node_updatebekerja untuk saya. Saya berasumsi bahwa field_attach_insert('node', $node)pada akhirnya hook_node_insertakan berhasil juga. Jadi, fungsi sampel akan terlihat seperti ini:

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

Tidak perlu menelepon node_load node_saveatau mengembalikan apa pun.

Saya pikir alasan untuk ini adalah bahwa node_save, dari mana hook_node_updatedan hook_node_insertdipanggil, membungkus semua permintaan basis data dalam suatu transaksi. (Perhatikan baris pertama node_save:. $transaction = db_transaction()) Kueri ini tidak dipanggil hingga node_saveselesai. Kueri terakhir yang node_savemenambah transaksi dipanggil dari field_attach_update, yang menggunakan objek $ node seperti sebelumnya hook_node_update disebut. Jadi, Anda perlu mengantri permintaan lain dengan menelepon field_attach_updatelagi. Setidaknya, itulah pemahaman saya tentang apa yang terjadi.

Jika Anda kesulitan mengubah atribut non-bidang dari simpul (mis., $node->log), Coba panggil _node_save_revision($node, $user->uid, 'vid');juga. Ini tidak akan membuat revisi baru.


2

Ini adalah bagaimana Anda mengubah nilai pada sebuah node:

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

4
undtidak benar-benar sesuai di sini, OP telah menyatakan dalam kode yang mereka gunakan $node->languageuntuk kode bahasa
Clive

Itu sangat membantu, terima kasih Clive dan Lance, tapi saya ingin memastikan nilai field disimpan setiap kali node disimpan, maka saya menggunakan hook_node_update. Apakah mungkin untuk mengembalikan $ node dalam hook ini atau apakah saya benar-benar harus melakukan node_load? Saya benar-benar berpikir saya memiliki objek node dilewatkan secara langsung melalui hook_node_update ....
generalconsensus

Ok jadi saya memperbarui kode sesuai rekomendasi Anda - itu di tubuh asli. Masalah: Loop tak berujung di mana halaman tidak memuat dan mysql dan apache mulai mencapai ke atas beban 85% pada cpu. Pasti ada beberapa perulangan yang terjadi di sini. Ada saran lain?
generalconsensus

Saya tidak bisa memberi tahu Anda apa yang sedang terjadi. Tapi mungkin Anda mencoba sekali untuk hanya memuat node, masukkan sesuatu di lapangan dan simpan menggunakan node_save (). Atau hanya memuat, mencetak sesuatu (menggunakan anjing penjaga atau dpm () dan menyimpannya lagi untuk melihat apakah ini bekerja.
Lance

Masalah ini berasal dari telah menyimpan node sebelum menyimpannya menghasilkan loop rekursif. Pilihan hook yang buruk dan build yang buruk
generalconsensus

1

Peningkatan solusi Lance di atas, menghindari penghematan seluruh node ketika hanya beberapa nilai bidang yang dimodifikasi:

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

Ini juga bisa bermanfaat untuk menghindari efek samping node_save().

Sumber: Menyimpan bidang simpul tanpa menyimpan simpul itu sendiri

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.