วิธีลบโปรแกรมออกจากโหนดโดยทางโปรแกรมหรือไม่


16

หนึ่งจะลบฟิลด์จากโหนดโดยทางโปรแกรมอย่างไร ฉันมีการย้ายhook_update_Nที่ย้ายเนื้อหาจากเขตข้อมูล aa ไปยังตารางที่กำหนดเอง หลังจากการโยกย้ายนั้นฉันต้องการลบเขตข้อมูลในฟังก์ชันเดียวกันนั้น

มี API ฟิลด์ใดที่รองรับการลบฟิลด์หรือไม่

แก้ไข, แก้ไข : เนื่องจากคำตอบไม่มีรหัสจริงนี่คือสิ่งที่ฉันได้ย้ายเขตข้อมูลจากผู้ใช้ $ ไปยังบันทึกของตัวเองและจากนั้นลบเขตข้อมูลจากฐานข้อมูล;

function my_module_update_7005(&$sandbox) {
  $slice = 100;
  //Fetch users from database;
  if (!isset($sandbox['progress'])) {
    $sandbox['progress'] = 0;
    $sandbox['current_uid'] = 0;
    // We'll -1 to disregard the uid 0...
    $sandbox['max'] = db_query('SELECT COUNT(DISTINCT uid) FROM {users}')->fetchField() - 1;
  }
  if (empty($users)) {
    $sandbox["current_uid"] += $slice;
  }
  $users = db_select('users', 'u')
    ->fields('u', array('uid', 'name'))
    ->condition('uid', $sandbox['current_uid'], '>')
    ->range(0, $slice)
    ->orderBy('uid', 'ASC')
    ->execute();
  //Loop trough users;
  foreach ($users as $user) {
    $foo = new Foo();
    // Warning: drupal's fields return mixed values; e.g. NULL versus an int.
    $foo->debits = (int) $user->user()->field_credits["und"][0]["value"];
    $foo->save();

    $sandbox['progress']++;
    $sandbox['current_uid'] = $user->uid;
  }

  $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);

  // Remove the field.
  field_delete_field("field_credits"); //note that the name for Foo is field_foo
  field_purge_batch($sandbox['max']+1);//Drupal seems to have an offbyone problem.
}

คำตอบ:


29

field_delete_field($field_name)จะทำเครื่องหมายการ$field_nameลบสำหรับการเรียกใช้ cron ครั้งต่อไป

คุณสามารถใช้field_purge_batchเพื่อทำการลบหากคุณไม่ต้องการที่จะทำในการทำงาน cron

แก้ไข: field_delete_field()ควรใช้เมื่อคุณต้องการลบฟิลด์จากบันเดิลอื่นเช่นกัน หากคุณต้องการลบฟิลด์จากกลุ่มเฉพาะคุณควรใช้field_delete_instance()ตามที่ระบุโดย @Clive


4
ระวังที่จะลบสนามจากกลุ่มอื่น ๆ มันอาจจะติดกับ :) ดีใจที่ได้รู้field_purge_batchว่า
Clive

@Clive: ถูกต้องมันจะลบฟิลด์จากบันเดิลทั้งหมด ขอบคุณสำหรับการแก้ไข :) ฉันได้แก้ไขคำตอบแล้ว
AjitS

ฉันต้องการลบฟิลด์ทั้งหมดเช่นจากกลุ่มทั้งหมด แต่คำเตือนนั้นดี ขอบคุณ
berkes

1
field_delete_instance () เป็นวิธีที่จะไป
Ryan McVeigh

field_purge_batch () จริง ๆ แล้วจะลบรายการฟิลด์ได้มากเท่าขนาดแบทช์ที่ถูกส่งผ่านไป สิ่งนี้อาจช่วยได้เมื่อฟิลด์มีไอเท็มเพียงไม่กี่รายการเท่านั้นดังนั้นเพื่อกำจัดอินสแตนซ์ของฟิลด์อย่างสมบูรณ์คุณไม่จำเป็นต้องรอให้ cron ล้างออก หากคุณมีค่าจำนวนมากในเขตข้อมูลอย่าถูกล่อลวงให้เพิ่มขนาดแบตช์สูงเกินไป ("แบทช์" ในชื่อไม่ได้หมายความว่ามันจะทำการแบตช์เองก็หมายความว่ามันทำแบตช์เดียว ของรายการให้มากที่สุดเท่าที่คุณขอ); คุณอาจทำงานในหน่วยความจำ PHP หรือ จำกัด เวลา
Eelke Blok

24

ในการลบฟิลด์ออกจากบันเดิลที่ต้องการคุณสามารถใช้ field_delete_instance()

ทำเครื่องหมายอินสแตนซ์ของฟิลด์และข้อมูลสำหรับการลบ

ตัวอย่าง:

function my_module_update_7001() {
  if ($instance = field_info_instance('node', 'field_name', 'page'))  {
    field_delete_instance($instance, TRUE);
    field_purge_batch(1);
  }
}

หากต้องการลบฟิลด์ออกจากระบบโดยสมบูรณ์คุณสามารถใช้ field_delete_field()

ทำเครื่องหมายฟิลด์และอินสแตนซ์และข้อมูลสำหรับการลบ

ตัวอย่าง:

function my_module_update_7001() {
  field_delete_field('field_name');
  field_purge_batch(1);
}

ฟิลด์ / อินสแตนซ์ถูกทำเครื่องหมายสำหรับการลบเท่านั้นข้อมูลจะถูกล้างในระหว่างการทำงาน cron ที่ตามมา หากต้องการล้างมันด้วยตนเองให้เรียกใช้งาน:

field_purge_batch(1);

1
ในขณะที่เรียกร้องfield_delete_field()และfield_purge_batch()ผลงานที่จะช่วยให้การบันทึกในและfield_config_instance field_configทำไมถึงเป็นอย่างนั้น?
berkes

ฉันไม่เข้าใจว่าทำไมการโทรถึง field_purge_batch ด้วยค่า 1 จะกำจัดข้อมูลฟิลด์ทั้งหมด ถ้าฉันเข้าใจรหัสอย่างถูกต้องมันจะได้รับข้อมูลภาคสนามสำหรับหน่วยงาน $ batchsize และปล่อยไว้ที่นั้น (เช่นไม่มีการเรียกฟังก์ชันซ้ำหรืออะไรก็ตาม) ดูเหมือนว่ามันจะขึ้นอยู่กับผู้โทรเพื่อตรวจสอบว่าข้อมูลทั้งหมดหายไปหรือไม่และถ้าไม่ให้เรียกใช้ฟังก์ชันต่อไป แต่บางทีฉันอาจเข้าใจผิดบางอย่าง
Eelke Blok

ที่จริงแล้วความคิดเห็นนี้ใน field_ui.admin.inc เป็นทางยาวในการอธิบายสิ่งนี้: // การล้างข้อมูลบน cron อย่างไรก็ตามโมดูลสนามป้องกันการปิดการใช้งานโมดูล // เมื่อประเภทฟิลด์ที่พวกเขาให้ถูกนำมาใช้ในสนามจนกว่ามันจะถูกลบออกอย่างสมบูรณ์ / ในกรณีที่เขตข้อมูลมีเนื้อหาน้อยที่สุดหรือไม่มีเลยการเรียก // ไปยัง field_purge_batch () เพียงครั้งเดียวจะลบออกจากระบบ เรียกสิ่งนี้โดยมีขีด จำกัด // ต่ำเพื่อหลีกเลี่ยงผู้ดูแลระบบที่ต้องรอ cron รันเมื่อ // ลบอินสแตนซ์ที่ตรงตามเกณฑ์นี้
Eelke Blok

@ ไคลฟ์ฉันเชื่อว่าคุณกำลังแนะนำโดยปริยาย แต่ฉันไม่สามารถเข้าใจได้ว่ามันแปลกสำหรับฉันที่จะมีการประกาศในเงื่อนไขหาก มีจุดประสงค์หรือไม่? $instance = field_info_instance('node', 'field_name', 'page')ผมหมายถึง ไม่ควรแทนที่จะเป็น$instance = field_info_instance('node', 'field_contact', 'job');แล้วปล่อยคำสั่ง if?
cdmo

1
@cdmo ก็เรียกว่า "ได้รับมอบหมายให้อยู่ในสภาพ" และใช่มันไม่ได้มีปัญหา แต่ Drupal core ใช้อย่างอิสระแม้กระทั่งในเวอร์ชั่นล่าสุดดังนั้นจึงมีแบบอย่างน้อย ความซื่อสัตย์เมื่อ 5 ปีที่แล้วและตอนนี้ฉันก็ฉลาดขึ้นฉันไม่ได้ใช้หรือไม่ว่าจะด้วยเหตุผลใดก็ตามฉันจะปิดงานที่มอบหมาย (เช่นif ( ($foo = $bar) ) {ดังนั้นความตั้งใจชัดเจนและศักยภาพ สำหรับข้อผิดพลาดมี จำกัด ถ้าคำสั่งตัวเองเป็นสิ่งที่จำเป็นเพราะfield_delete_instanceไม่ได้ตรวจสอบเป็นโมฆะ
Clive

5

ในการตอบคำถาม @berkes:

field_delete_field()ทำเครื่องหมายเขตข้อมูลสำหรับการลบทำให้การล้างข้อมูลในการเรียกใช้ cron ครั้งต่อไป อย่างไรก็ตามมันจะเก็บข้อมูลไว้field_config_instanceเกี่ยวกับฟิลด์ที่ถูกดร็อป กำลังรัน cron หรือfield_purge_batch()จะไม่ลบข้อมูลนี้ออกจากfield_config_instanceตารางแม้ว่าจะมีการตั้งค่าคอลัมน์ที่ถูกลบ1สำหรับเขตข้อมูล

สำหรับฉันที่ใช้field_delete_instance()แล้วตามด้วยfield_purge_batch()สำหรับแต่ละเขตข้อมูลที่ถูกลบทำงาน - ลบทั้งสองเขตข้อมูลออกจากฐานข้อมูล (โดยไม่ต้องใช้ cron) เช่นเดียวกับการล้างfield_config_instanceตารางของข้อมูลเขตข้อมูลใด ๆ (สำหรับเขตข้อมูลที่ถูกลบ)

นี่คือทางออก:

/**
 * Implements hook_uninstall().
 */
function hook_uninstall() {
  // Delete all fields for all xyz entity bundles.

  // Retrieve all bundles for an entity.
  $bundles = field_info_bundles('XYZ'); // The name of your entity type, for example, 'node'.
  foreach ($bundles as $bundle => $properties) {

    // Retrieve all the fields for a given bundle.
    $instances = field_info_instances('XYZ', $bundle);
    foreach ($instances as $instance) {
      field_delete_instance($instance, TRUE);
      field_purge_batch(1);
    }
  }
}

ทำเครื่องหมายTRUEon field_delete_instance()เนื่องจากเป็นการระบุว่า Field API ควรทำการดำเนินการล้างข้อมูล


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