Làm cách nào để thay đổi loại trường?


9

Tôi có một loại nội dung với một trường_maps có loại là Văn bản (đơn giản, dài) . Tôi cần phải thay đổi nó thành Văn bản (đơn giản) .

Vì vậy, tôi đã thực hiện câu lệnh SQL này:

ALTER TABLE node__field_maps MODIFY field_maps_value VARCHAR(200);

Có vẻ như field_type đã thay đổi thành VARCHAR(200), nhưng vẫn còn một vấn đề nữa: Trên các loại nội dung và các tab trường quản lý, trường vẫn được hiển thị dưới dạng Văn bản (đơn giản, dài) .

Làm cách nào để thay đổi nó thành Văn bản (đơn giản) ?


Bạn có dữ liệu sản xuất trong cơ sở dữ liệu? Bởi vì cách dễ nhất là xóa trường cũ và cài đặt nó theo ý muốn.
Mắt

1
@Hefi bạn có thể thử câu trả lời của tôi cho một Q. tương tự. Bạn luôn có thể đặt trang web của mình ở chế độ bảo trì trong vài giây / phút trong khi bạn làm điều đó. Thực hiện chạy khô trên máy chủ test / dev trước.
Không có Sssweat

1
Bạn nên viết một móc cập nhật để thực hiện nhiệm vụ này. Về cơ bản, bạn sẽ cần sao chép dữ liệu vào một biến, xóa trường cài đặt trường mới và chèn lại dữ liệu. (Tất cả trong cùng một chức năng cập nhật)
Eyal

Câu trả lời:


13

Tôi cũng đã nhận được loại vấn đề này thay đổi loại trường từ loại này sang loại khác với dữ liệu hiện có. Vì vậy, như @Eyal đã đề cập, chúng ta có thể viết một bản cập nhật để

  1. xuất dữ liệu từ bảng trường sang biến
  2. loại bỏ các trường của tất cả các gói
  3. thêm các lĩnh vực mới của tất cả các gói
  4. khôi phục dữ liệu vào bảng trường

Đây là ví dụ mã

use \Drupal\field\Entity\FieldStorageConfig;
use \Drupal\field\Entity\FieldConfig;

/**
 * Change node__field_maps from string_long to string type.
 */
function mymodule_update_8XXX() {
  $database = \Drupal::database();
  $table = 'node__field_maps';
  $entity_type = 'node';
  $field_name = 'field_maps';

  $field_storage = FieldStorageConfig::loadByName($entity_type, $field_name);

  if (is_null($field_storage)) {
    return;
  }

  $rows = NULL;

  if ($database->schema()->tableExists($table)) {
    // The table data to restore after the update is completed.
    $rows = $database->select($table, 'n')
      ->fields('n')
      ->execute()
      ->fetchAll();
  }

  $new_fields = array();

  // Use existing field config for new field.
  foreach ($field_storage->getBundles() as $bundle => $label) {
    $field = FieldConfig::loadByName($entity_type, $bundle, $field_name);
    $new_field = $field->toArray();
    $new_field['field_type'] = 'string';
    $new_field['settings'] = array();

    $new_fields[] = $new_field;
  }

  // Deleting field storage which will also delete bundles(fields).
  $new_field_storage = $field_storage->toArray();
  $new_field_storage['type'] = 'string';
  $new_field_storage['settings'] = array(
    'max_length' => 255,
    'is_ascii' => FALSE,
    'case_sensitive' => FALSE,
  );

  $field_storage->delete();

  // Purge field data now to allow new field and field_storage with same name
  // to be created. You may need to increase batch size.
  field_purge_batch(10);

  // Create new field storage.
  $new_field_storage = FieldStorageConfig::create($new_field_storage);
  $new_field_storage->save();

  // Create new fields.
  foreach ($new_fields as $new_field) {
    $new_field = FieldConfig::create($new_field);
    $new_field->save();
  }

  // Restore existing data in the same table.
  if (!is_null($rows)) {
    foreach ($rows as $row) {
      $database->insert($table)
        ->fields((array) $row)
        ->execute();
    }
  }

}

LƯU Ý: Luôn sao lưu DB và mã kiểm tra trước khi chạy mã này

Những suy nghĩ khác Trong trường hợp của tôi, chúng tôi cũng đã xuất cấu hình, có nghĩa là loại trường và cài đặt cũng được bao gồm trong các tệp cấu hình field_st Storage_config, field_config, entity_form_display và entity_view_display. Vì vậy, chúng tôi phải cập nhật cài đặt cấu hình trong các tệp đó. Một cách dễ dàng có thể là:

  • nhân bản trang web của bạn
  • xóa trường và thêm một trường có cùng tên một lần nữa trong giao diện người dùng trường
  • cấu hình xuất để sử dụng chúng trong repo
  • đảm bảo cấu hình uuid cho trường và bộ lưu trữ không bị thay đổi (thay đổi lại uuid nếu có) để tránh việc nhập dữ liệu có khả năng xóa dữ liệu.
  • nhập cấu hình sau khi cập nhật DB và xóa bộ nhớ cache một lần nữa

Đây là mã được lấy cảm hứng từ @drugan trong bài đăng https://www.drupal.org/node/2816859


1
Mã tuyệt vời - cảm ơn !! Tôi đã làm điều này để làm việc cho một sự thay đổi lĩnh vực tương tự. Xin lưu ý, trường mới sẽ bị vô hiệu hóa trong màn hình biểu mẫu .. Tôi không nghĩ nó hoạt động lúc đầu nhưng sau đó nhận ra nó chỉ bị vô hiệu hóa.
xe lăn

Tôi đã sao chép nội dung bằng cách thực hiện sao chép bảng và đổi tên trường và giá trị bảng. giá trị hiện đang hiển thị trong các trường mới và tôi đã chuyển nội dung từ văn bản đơn giản sang số. Bây giờ tôi đã thiết lập sắp xếp theo số (số nguyên) .its vẫn hiển thị theo văn bản thuần 10 hơn 2. giải pháp nào cho việc này cần sự giúp đỡ của bạn?
Manmeet Khurana

Mặc dù hook cập nhật thực sự hoạt động, nhưng đã thử nghiệm trên một số trường khác nhau, việc xử lý đề xuất cấu hình sẽ khiến bạn mất tất cả dữ liệu được lưu trữ vào trường đã nói, vì quá trình nhập cấu hình sẽ xem các cấu hình dưới dạng các trường riêng biệt và xóa bản gốc với nó nội dung trước khi thêm cái mới. Để tránh điều này, một khi bạn xuất cấu hình, hãy đảm bảo rằng uuid của cấu hình KHÔNG bị thay đổi (về cơ bản thay đổi lại thành uuid của trường ban đầu) theo cách đó hệ thống cấu hình sẽ cho rằng đó là cùng một trường và chỉ cập nhật nó. Tôi đã chỉnh sửa câu trả lời của bạn để bao gồm thông tin này.
Dion S. Jensen

0

Tôi đã phải đối mặt với một vấn đề tương tự. Sau khi chạy update_hook được mô tả, tôi vẫn phải đối mặt với một thông báo về "Thực thể không khớp và / hoặc định nghĩa trường" trên trang tổng quan trạng thái. Tôi nghĩ rằng đó là do entup drush bị xóa trong Drupal 8.7 Tôi đã có thể giải quyết vấn đề này bằng cách buộc thủ công cập nhật FieldStorageDefDef như thế này:

function my_module_update_8002() {
  $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
  $entity_type = '[my_entity_type]';
  $field_name = '[my_field_name]';
  $field_storage = FieldStorageConfig::loadByName($entity_type, $field_name);
  $entity_definition_update_manager->updateFieldStorageDefinition($field_storage);
}
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.