Làm thế nào để lập trình loại bỏ một trường từ một nút?


16

Làm thế nào để loại bỏ một trường từ một nút lập trình? Tôi có một di chuyển trong hook_update_Nđó di chuyển nội dung từ trường aa vào một bảng tùy chỉnh. Sau khi di chuyển, tôi muốn loại bỏ trường trong cùng chức năng đó.

Có bất kỳ API trường nào phục vụ loại bỏ các trường không?

Chỉnh sửa, Giải pháp : Vì các câu trả lời thiếu mã thực tế, đây là những gì tôi đã làm để chuyển các trường từ người dùng $ vào hồ sơ của riêng tôi và sau đó xóa trường khỏi cơ sở dữ liệu;

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.
}

Câu trả lời:


29

field_delete_field($field_name)sẽ đánh dấu việc $field_namexóa trong lần chạy cron tiếp theo.

Bạn có thể sử dụng field_purge_batchđể xóa, nếu bạn không muốn thực hiện khi chạy cron.

EDIT: field_delete_field() nên được sử dụng khi bạn cần xóa trường khỏi các gói khác. Nếu bạn chỉ muốn xóa trường khỏi một gói cụ thể, bạn nên sử dụng field_delete_instance()như được đề cập bởi @Clive.


4
Cẩn thận, điều đó cũng sẽ xóa trường khỏi bất kỳ gói nào khác mà nó có thể được đính kèm :) field_purge_batchMặc dù vậy cũng tốt để biết
Clive

@Clive: đúng, nó sẽ xóa trường mẫu tất cả các gói. Cảm ơn bạn đã sửa :) Tôi đã chỉnh sửa câu trả lời.
AjitS

Tôi đã muốn loại bỏ hoàn toàn các lĩnh vực, tức là từ tất cả các gói. Nhưng cảnh báo là tốt. Cảm ơn.
cập bến

1
field_delete_instance () là cách để đi.
Ryan McVeigh

field_purge_batch () trên thực tế sẽ chỉ xóa bao nhiêu mục trường theo kích thước lô được truyền cho nó. Điều này có thể giúp ích khi trường chỉ có một vài mục, do đó để loại bỏ hoàn toàn trường hợp trường, bạn không cần đợi cron dọn sạch. Nếu bạn có nhiều giá trị trong trường, đừng cố tăng kích thước lô quá cao ("lô" trong tên không có nghĩa là nó sẽ tự thực hiện bất kỳ lô nào, điều đó chỉ có nghĩa là nó thực hiện một đợt duy nhất của nhiều mặt hàng như bạn yêu cầu); cuối cùng bạn có thể chạy vào bộ nhớ PHP hoặc giới hạn thời gian.
Eelke Blok

24

Để xóa một trường khỏi một gói cụ thể, bạn có thể sử dụng field_delete_instance()

Đánh dấu một thể hiện trường và dữ liệu của nó để xóa.

Thí dụ:

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

Để xóa hoàn toàn một trường khỏi hệ thống, bạn có thể sử dụng field_delete_field()

Đánh dấu một trường và các trường hợp và dữ liệu của nó để xóa.

Thí dụ:

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

Các trường / trường hợp chỉ được đánh dấu để xóa, dữ liệu sẽ thực sự bị xóa trong các lần chạy cron tiếp theo. Để thanh trừng nó thực hiện thủ công:

field_purge_batch(1);

1
Trong khi gọi field_delete_field()field_purge_batch()làm việc, nó giữ hồ sơ trong field_config_instancefield_config. Tại sao vậy?
cập bến

Tôi hoàn toàn không hiểu tại sao gọi field_purge_batch với giá trị 1 sẽ loại bỏ tất cả dữ liệu trường. Nếu tôi hiểu mã chính xác, nó sẽ lấy dữ liệu trường cho các thực thể $ batchsize và để nó ở đó (nghĩa là không gọi hàm đệ quy, hoặc bất cứ thứ gì); Dường như người gọi phải kiểm tra xem tất cả dữ liệu đã hết chưa và nếu không, hãy tiếp tục gọi hàm. Nhưng có lẽ về cơ bản tôi đang hiểu nhầm điều gì đó.
Eelke Blok

Trên thực tế, nhận xét này trong field_ui.admin.inc đi một chặng đường dài để giải thích điều này: // Các trường được thanh trừng trên cron. Tuy nhiên, mô-đun trường ngăn chặn việc vô hiệu hóa các mô-đun // khi các loại trường mà chúng cung cấp được sử dụng trong một trường cho đến khi nó được loại bỏ hoàn toàn. Trong trường hợp một trường có tối thiểu hoặc không có nội dung, một lệnh gọi // đến field_purge_batch () sẽ xóa nó khỏi hệ thống. Gọi điều này với // giới hạn lô thấp để tránh quản trị viên phải chờ cron chạy khi // xóa các trường hợp đáp ứng tiêu chí này.
Eelke Blok

@Clive, tôi tin tưởng lời khuyên của bạn khá rõ ràng, nhưng tôi không thể hiểu được việc tôi khai báo trong điều kiện if có vẻ kỳ lạ như thế nào. Đó có phải là mục đích? Tôi đang đề cập đến $instance = field_info_instance('node', 'field_name', 'page'). Không nên thay vào đó $instance = field_info_instance('node', 'field_contact', 'job');và sau đó bỏ câu lệnh if?
cdmo

1
@cdmo nó được gọi là "gán trong điều kiện", và vâng, nó có vấn đề . Nhưng lõi Drupal sử dụng nó một cách tự do, ngay cả trong phiên bản mới nhất, vì vậy ít nhất nó đã có tiền lệ. Thành thật mà nói, điều này đã xảy ra cách đây 5 năm và bây giờ tôi đã khôn ngoan hơn một chút, tôi sẽ không sử dụng nó, hoặc nếu vì bất kỳ lý do gì tôi sẽ làm, tôi sẽ hoàn thành nhiệm vụ (ví dụ như if ( ($foo = $bar) ) {vậy là ý định rõ ràng và tiềm năng cho lỗi bị giới hạn. Bản thân câu lệnh if là cần thiết vì field_delete_instancekhông kiểm tra null
Clive

5

Để trả lời câu hỏi @berkes:

field_delete_field()không đánh dấu trường để xóa, làm cho nó bị xóa trong lần chạy cron tiếp theo. Tuy nhiên, nó không để lại dữ liệu field_config_instancevề trường bị rơi. Chạy cron hoặc field_purge_batch()sẽ không xóa dữ liệu này khỏi field_config_instancebảng, ngay cả khi cột đã xóa được đặt thành 1cho trường.

Đối với tôi, việc sử dụng field_delete_instance()theo sau là field_purge_batch()cho mỗi trường bị xóa hoạt động - loại bỏ ngay cả trường khỏi cơ sở dữ liệu (không yêu cầu cron), cũng như xóa field_config_instancebảng của bất kỳ dữ liệu trường nào (đối với trường đã xóa).

Đây là giải pháp:

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

Đừng chú ý TRUEtrên field_delete_instance(), vì nó chỉ ra rằng API Dòng nên thực hiện hoạt động dọn dẹp.


Làm thế nào để sử dụng mã này? Tôi muốn xóa trường tiêu đề khỏi một loại nội dung
Umair
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.