การอัพเดตฟิลด์โดยทางโปรแกรม hook_node_update


13

ขณะนี้พยายามอัปเดตฟิลด์ทุกครั้งที่มีการสร้างหรืออัปเดตโหนด อย่างไรก็ตามค่าไม่ได้ถูกบรรจุภายในโหนดฉันจะสามารถเข้าถึงวัตถุโหนดด้วยเบ็ดนี้โดยเฉพาะหรือไม่? ฉันจะพลาดอะไรได้บ้าง

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

    }

คำตอบ:


16

เอนทิตี wraps ข้อมูลเมตา

API เอนทิตีจัดเตรียมคลาส wrapper บางคลาสที่คุณอาจใช้เพื่อจัดการกับเอนทิตีได้ง่ายและใช้ประโยชน์จากโมดูลข้อมูลคุณสมบัติเอนทิตีที่มีให้ ด้วยความช่วยเหลือของ wrappers คุณสามารถเข้าถึงข้อมูลคุณสมบัติวนรอบคุณสมบัติที่รู้จักหรือเพียงแค่รับ / ตั้งค่าข้อมูลที่อธิบายไว้ ฯลฯ

นี่คือตัวอย่างการใช้งานง่าย ๆ ที่พบใน README:

สำหรับการใช้ข้อมูลนี้ (ข้อมูลเมตา) โมดูลให้คลาส wrapper บางคลาสที่ช่วยให้การรับและตั้งค่าง่ายขึ้น wrapper รองรับการใช้งานที่ถูกล่ามโซ่สำหรับการดึง wrappers ของคุณสมบัติเอนทิตีเช่นเพื่อรับที่อยู่อีเมลของผู้เขียนโหนดที่สามารถใช้ได้:

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

เพื่อปรับปรุงที่อยู่อีเมลของผู้ใช้สามารถใช้

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

หรือ

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

wrappers จะส่งคืนข้อมูลตามที่อธิบายไว้ในข้อมูลคุณสมบัติซึ่งอาจถูกดึงโดยตรงผ่าน entity_get_property_info () หรือจาก wrapper:

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

เพื่อที่จะบังคับให้ได้รับคุณค่าทางใจสำหรับการส่งออกหนึ่งสามารถใช้เช่น

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

เพื่อรับชื่อโหนดที่ถูกสุขลักษณะ เมื่อคุณสมบัติถูกส่งคืนโดยค่าเริ่มต้นเช่นเดียวกับโหนดเนื้อหาหนึ่งอาจต้องการรับข้อมูลที่ไม่ได้รับการฆ่าเชื้อตามที่ปรากฏในเบราว์เซอร์สำหรับกรณีการใช้งานอื่น ในการทำเช่นนั้นสามารถเปิดใช้งานตัวเลือก 'ถอดรหัส' ซึ่งทำให้มั่นใจได้ว่าข้อมูลที่ถูกสุขลักษณะจะถูกปล้นและแท็ก HTML จะถูกถอดรหัสก่อนที่คุณสมบัติจะถูกส่งคืน:

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

วิธีนั้นจะได้รับข้อมูลตามที่ปรากฏแก่ผู้ใช้เสมอ อย่างไรก็ตามหากคุณต้องการได้รับข้อมูลดิบที่ไม่ได้ประมวลผลแม้กระทั่งข้อมูลที่เป็นข้อความที่ถูกสุขอนามัยคุณสามารถทำได้ผ่าน:

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

ตัวอย่างเพิ่มเติม:

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

เอกสารเพิ่มเติม : http://drupal.org/node/1021556


ขอบคุณมาก. คำตอบของคุณช่วยให้ฉันทราบทิศทางที่ฉันต้องทำ :) ชุมชนหิน !! \ m /
SGhosh

สิ่งนี้จะใช้งานได้กับ hook_node_update แต่ไม่สามารถใช้กับ hook_node_insert () คุณจะได้รับข้อผิดพลาดคีย์หลักที่ซ้ำกันจาก mysql เนื่องจากทั้งโมดูลโหนดและรหัสที่กำหนดเองของคุณจะพยายามแทรกโหนดเดียวกันสองครั้ง (ใช้รหัสโหนดเดียวกัน)
leon.nk

14

โทรมาหาฉันfield_attach_update('node', $node)ตอนจบ hook_node_updateฉันคิดว่าfield_attach_insert('node', $node)ในตอนท้ายของการhook_node_insertทำงานก็เช่นกัน ดังนั้นฟังก์ชั่นตัวอย่างจะมีลักษณะเช่นนี้:

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

ไม่จำเป็นต้องโทรnode_load node_saveหรือส่งคืนอะไร

ผมคิดว่าเหตุผลของเรื่องนี้ก็คือว่าnode_saveจากการที่hook_node_updateและhook_node_insertจะเรียกว่าแรปสืบค้นฐานข้อมูลทั้งหมดในการทำธุรกรรม (สังเกตบรรทัดแรกของnode_save: $transaction = db_transaction().) คำค้นหาเหล่านี้จะไม่ถูกเรียกจนกว่าจะnode_saveเสร็จสิ้น แบบสอบถามสุดท้ายที่node_saveเพิ่มไปยังธุรกรรมถูกเรียกใช้จากfield_attach_updateซึ่งใช้วัตถุ $ node เหมือนเดิมที่ hook_node_updateเรียกว่า ดังนั้นคุณต้องเข้าคิวคิวรีอื่นโดยการโทรfield_attach_updateอีกครั้ง อย่างน้อยฉันก็เข้าใจว่าเกิดอะไรขึ้น

หากคุณมีปัญหาในการเปลี่ยนแอตทริบิวต์ที่ไม่ใช่ฟิลด์ของโหนด (เช่น$node->log) ลองโทร_node_save_revision($node, $user->uid, 'vid');ด้วย สิ่งนี้จะไม่สร้างการแก้ไขใหม่


2

นี่คือวิธีที่คุณเปลี่ยนค่าบนโหนด:

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

4
undไม่เหมาะสมจริงๆที่นี่ OP ได้ระบุไว้ในรหัสที่พวกเขาใช้$node->languageสำหรับรหัสภาษา
ไคลฟ์

นั่นเป็นประโยชน์อย่างมากขอบคุณ Clive และ Lance แต่ฉันต้องการตรวจสอบให้แน่ใจว่าได้บันทึกค่าฟิลด์ทุกครั้งที่มีการบันทึกโหนดดังนั้นการใช้ hook_node_update ของฉัน เป็นไปได้ไหมที่จะส่งกลับ $ node ใน hook นี้หรือฉันต้องทำ node_load หรือไม่? ฉันคิดว่าฉันมีวัตถุโหนดที่ส่งผ่านโดยตรงผ่าน hook_node_update ....
generalconsensus

ตกลงดังนั้นฉันปรับปรุงรหัสตามคำแนะนำของคุณ - มันอยู่ในร่างกายเดิม ปัญหา: ลูปที่ไม่มีที่สิ้นสุดที่หน้าไม่โหลดและทั้ง mysql และ apache จะเริ่มโจมตีโหลดซีพียูได้สูงถึง 85% มีการวนซ้ำเกิดขึ้นที่นี่ ข้อเสนอแนะอื่น ๆ ?
สำรวจทั่วไปใน

ฉันไม่สามารถบอกคุณได้ว่าเกิดอะไรขึ้น แต่คุณอาจลองหนึ่งครั้งเพื่อโหลดโหนดป้อนบางสิ่งในฟิลด์และบันทึกโดยใช้ node_save () หรือเพียงแค่โหลดพิมพ์บางอย่าง (โดยใช้ watchdog หรือ dpm () และบันทึกอีกครั้งเพื่อดูว่ามันใช้งานได้ไหม
Lance

ปัญหานี้ได้มาจากการบันทึกโหนดก่อนที่จะบันทึกทำให้เกิดวนซ้ำ ทางเลือกที่น่าสงสารและงานสร้างที่ไม่ดี
สำรวจทั่วไป

1

การปรับปรุงโซลูชันของแลนซ์ด้านบนหลีกเลี่ยงการบันทึกโหนดทั้งหมดเมื่อมีการแก้ไขค่าฟิลด์เพียงเล็กน้อย:

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

node_save()นอกจากนี้ยังอาจจะมีประโยชน์ที่จะหลีกเลี่ยงผลข้างเคียงของ

ที่มา: การบันทึกฟิลด์ของโหนดโดยไม่บันทึกโหนดเอง

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.