Làm cách nào để thay đổi loại trường từ Số nguyên sang Số thập phân?


7

Tôi có một loại nội dung với một trường nội dung số nguyên. Trường cần chứa dữ liệu nổi. Cách dễ nhất để thay đổi loại trường từ số nguyên sang số thập phân là gì? (Có hàng ngàn nút hiện tại tôi sẽ phải chuyển đổi).


Tôi đã tìm thấy một giải pháp trong bình luận nàybình luận này . Nó là tốt nhất?


Không. Điều đó liên quan đến Drupal 6 và CCK, câu hỏi này là về Drupal 7. Các trường trong D7 rất giống với CCK trong D6, nhưng không giống nhau. Cách tiếp cận chung có thể tốt, nhưng bạn sẽ cần phải thực hiện các chỉnh sửa để làm cho nó hoạt động trên D7.
Eelke Blok

Câu trả lời:


8

Chỉ cần hợp nhất tất cả các đề xuất trước đó vào một đoạn tiện lợi:

// Change this to your field name, obvs.
$field = 'field_myfieldname';

// Update the storage tables
$tables = array('field_data', 'field_revision');
foreach ($tables as $table) {
  $tablename = $table .'_'. $field;
  $fieldname = $field .'_value';
  db_change_field($tablename, $fieldname, $fieldname, array(
    'type' => 'numeric',
    'precision' => 10,
    'scale' => 2,
    'not null' => FALSE,
  ));
}

// Fetch the current field configuration
$field_config = db_query("SELECT data FROM {field_config} WHERE field_name = :field_name", array(
    ':field_name' => $field,
  ))
  ->fetchObject();
$data = unserialize($field_config->data);

// Update the settings entry
$data['settings'] = array(
  'precision' => 10,
  'scale' => 2,
  'decimal_separator' => '.',
);

// Store the new field config, update the field type at the same time
db_update('field_config')
  ->fields(array(
    'data' => serialize($data),
    'type' => 'number_decimal',
  ))
  ->condition('field_name', $field)
  ->execute();    

// If you are confident about what bundles have instances of this field you can
// go straight to the db_query with a hardcoded entity_type / bundle.
$instances = field_info_field_map();
foreach ($instances[$field]['bundles'] as $entity_type => $bundles) {
  foreach ($bundles as $bundle) {

    // Fetch the field instance data
    $field_config_instance = db_query("SELECT data FROM {field_config_instance}
                                       WHERE field_name = :field_name
                                       AND entity_type = :entity_type
                                       AND bundle = :bundle", array(
        ':field_name' => $field,
        ':entity_type' => $entity_type,
        ':bundle' => $bundle,
      ))
      ->fetchObject();
    $data = unserialize($field_config_instance->data);

    // Update it with the new display type
    $data['display']['default']['type'] = 'number_decimal';

    // Store it back to the database
    db_update('field_config_instance')
      ->fields(array('data' => serialize($data)))
      ->condition('field_name', $field)
      ->condition('entity_type', $entity_type)
      ->condition('bundle', $bundle)
      ->execute();

  }
}

Thêm một bổ sung; khi bạn có cấu hình không chuẩn với các chế độ hiển thị khác nhau, dòng được đánh dấu "Cập nhật nó với loại hiển thị mới" có thể tàn phá. Thay vào đó, bạn nên lặp qua tất cả các màn hình, trước tiên hãy kiểm tra xem trường không bị ẩn trong màn hình đó và cập nhật nó nếu không. Chỉnh sửa: Rõ ràng, tôi không thể đăng mã trong một bình luận.
Eelke Blok

1
Giải pháp tuyệt vời. Tôi đã sao chép nó vào chức năng có thể truy cập bằng hook_update_n và tắt các cuộc đua! Lưu ý: Và các khung nhìn, bảng điều khiển, vv hiển thị trường cũng sẽ cần cập nhật. Việc triển khai điều này trong hook_update_n có thể gây ra trục trặc và yêu cầu một chút xáo trộn giữa thay đổi trường và tính năng xuất khẩu hoàn nguyên nếu đó là túi của bạn.
texas-bronius

5

Cách tiếp cận tốt hơn có thể là sử dụng khả năng tích hợp sẵn của Drupal để thay đổi loại trường, db_change_field () .

db_change_field('field_data_field_number', 'field_number_value', 'field_number_value', array(
  'type' => 'numeric',
  'precision' => 10,
  'scale' => 2,
  'not null' => FALSE,
));

Điều quan trọng cần lưu ý đây không phải là một giải pháp hoàn chỉnh, chỉ là một cải tiến có thể có so với các giải pháp khác được đưa ra; điều này chỉ thay đổi loại cột cơ sở dữ liệu (trường), nó không thực hiện toàn bộ chuyển đổi trường Drupal. Về cơ bản, nó thay thế truy vấn ALTER thô được đưa ra ở nơi khác.
Eelke Blok

4

Tôi vừa viết một số mã sẽ xử lý việc này cho bạn trong mô-đun Trình trợ giúp của tôi : http://cgit.drupalcode.org/helper/tree/lib/FieldChangeHelper.php?h=7.x-1.x

FieldChangeHelper::changeType('my_int_field_name', 'number_decimal');

Nó sẽ hoạt động tốt cho hầu hết các trường hợp và trường đơn giản, nhưng nên được kiểm tra kỹ lưỡng. Hiện tại nó cũng không cập nhật bất kỳ trình định dạng trường nào, vì vậy bạn sẽ muốn xem lại cấu hình hiển thị cho trường sau khi chạy này.


Cái này nhìn rất đẹp! Bạn có thể vui lòng cho một số gợi ý về cách sử dụng các mô-đun của bạn cho người mới ở đây không :)
petergus

Một cái gì đó như thế này sẽ làm việc để chuyển đổi một văn bản thành loại liên kết?
Âm thanh

Điều này không hoạt động khá tốt ngay cả với phiên bản drupal mới nhất (hiện là 7.34).
todinov

Điều này không cho phép đặt độ chính xác và tỷ lệ. Theo mặc định, nó đặt độ chính xác thành 10 và tỷ lệ thành 2. Nếu bạn cần đặt các giá trị khác nhau, hãy xem câu trả lời của KingAndy.
Camilo

4

Dave Reids mô-đun drupal.org/project/helper ở trên là một giải pháp đơn giản tốt.

Không thể thêm bình luận ở trên để đăng các bước ở đây.

1) Tải xuống và kích hoạt mô-đun Helper

2) Tạo một tệp mới: changeIntField.php

<?php
FieldChangeHelper::changeType('my_int_field_name', 'number_decimal');
?>

3) Lưu tệp trong thư mục gốc nơi cài đặt drupal

4) thay đổi drush ScrIntField.php

5) Xóa tập tin changeIntFiled.php vì bạn không còn cần nó nữa.

6) Chỉnh sửa định dạng hiển thị cho nút / thực thể nơi trường đang được sử dụng.

7) Chỉnh sửa Chế độ xem - nơi trường được sử dụng và sửa các cài đặt định dạng hiển thị ở đây.


Điều này đã làm việc tuyệt vời! Nếu bạn đã cài đặt mô-đun Devel, bạn cũng có thể chạy mã này trực tiếp trên trang Mã Excute PHP.
ovi

PS bạn có một lỗi đánh máy nhỏ trong lệnh drush của bạn. nó nên làdrush scr
ovi

Truy cập phần thực thi php tại đây: / devel / php
Sam Thompson

Tại sao không chỉ drush php-eval "FieldChangeHelper::changeType('my_int_field_name', 'number_decimal');"?
milkovsky

2

Thay đổi loại trường nội dung Drupal 7 từ số nguyên sang số thập phân khá đơn giản. Không cần phải tạo một trường mới và sau đó sao chép định nghĩa. Tôi đã sử dụng ba bước sau:

  1. Tìm tên của bảng của trường và tên của trường trong bảng đó nơi lưu trữ giá trị của trường, sử dụng MySQL.

  2. Sử dụng thống kê thay đổi MySQL để thay đổi kiểu dữ liệu của trường:
    ALTER TABLE field_data_field_myfield MODIFY field_myfield_value decimal(10,2) ;

  3. Thay đổi định nghĩa trường trong Drupal:
    UPDATE field_config SET type = 'number_decimal' WHERE field_name = 'field_myfield';

Bước 1-3 là đủ. Mặc dù, trong một số trường hợp nhất định, có thể có ích khi so sánh các thuộc tính của một số nguyên và trường thập phân trên bảng field_config để xem liệu có gì khác cần phải thay đổi không : SELECT id, field_name, type, CONVERT(data USING utf8) FROM field_config WHERE type like 'number_%'.


2

Lưu ý rằng có một bảng khác cho mỗi trường được gọi là field_Vvision_field_ {field_name} và loại cột mysql của bảng này cũng sẽ thay đổi

Ngoài ra trường thập phân có các cài đặt khác nhau sẽ được đặt, sử dụng tập lệnh sau để hủy kích hoạt cài đặt trường sửa đổi nó và sau đó tuần tự hóa lại. Có hai bảng field_config và field_config_instance. sau đây là cho field_config

$s = unserialize('field_config table serialize string');

$s['settings'] = array (
    'precision' => '20',
    'scale' => '0',
    'decimal_separator' => '.',
);

print serialize($s);

đây là ví dụ cấu hình trường:

$s = unserialize('field_config_instance table serialize string');

$s['display']['default']['type'] = 'number_decimal';

print serialize($s);

LƯU Ý: các trường có thể có nhiều hơn một thể hiện và mã tiếp theo sẽ được sử dụng cho tất cả các thể hiện.

Bây giờ hãy xóa bộ nhớ cache của Drupal và chuyển đến cài đặt trường, chỉnh sửa trường và lưu nó. Nếu bạn không nhận được lỗi, có lẽ bạn nên đi :)


1

Tôi đã phải thay đổi một trường có tên là "field_margin_percentage" thành số thập phân

Bước 1 - Cập nhật các trường cơ sở dữ liệu

db_change_field('field_data_field_margin_percentage', 'field_margin_percentage_value', 'field_margin_percentage_value', array(
  'type' => 'numeric',
  'precision' => 10,
  'scale' => 2,
  'not null' => FALSE,
));

Bước 2 - Cập nhật trường_config để trường biết trình xử lý chính xác

db_query("UPDATE field_config SET type = 'number_decimal' WHERE field_name = 'field_margin_percentage'");

Bước 3 - Nhận cột 'dữ liệu' hiện có từ field_config và thêm cài đặt thập phân

$current_field_config = 'a:7:{s:12:"translatable";s:1:"0";s:12:"entity_types";a:0:{}s:8:"settings";a:0:{}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:34:"field_data_field_margin_percentage";a:1:{s:5:"value";s:29:"field_margin_percentage_value";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:38:"field_revision_field_margin_percentage";a:1:{s:5:"value";s:29:"field_margin_percentage_value";}}}}}s:12:"foreign keys";a:0:{}s:7:"indexes";a:0:{}s:2:"id";s:3:"161";}';

$s = unserialize($current_field_config);

$s['settings'] = array (
    'precision' => '10',
    'scale' => '2',
    'decimal_separator' => '.',
);

print serialize($s); // This will give you the new value for the data column (see below)

Bước 4 - Nhận cột 'dữ liệu' hiện có từ field_config_instance và thêm cài đặt thập phân

$s = unserialize('a:7:{s:5:"label";s:17:"Margin Percentage";s:6:"widget";a:5:{s:6:"weight";s:2:"13";s:4:"type";s:6:"number";s:6:"module";s:6:"number";s:6:"active";i:0;s:8:"settings";a:0:{}}s:8:"settings";a:7:{s:3:"min";s:1:"0";s:3:"max";s:3:"100";s:6:"prefix";s:0:"";s:6:"suffix";s:0:"";s:26:"commerce_user_profile_pane";i:0;s:35:"commerce_user_profile_pane_required";i:0;s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:14:"number_integer";s:6:"weight";s:2:"12";s:8:"settings";a:4:{s:18:"thousand_separator";s:1:" ";s:17:"decimal_separator";s:1:".";s:5:"scale";i:0;s:13:"prefix_suffix";b:1;}s:6:"module";s:6:"number";}}s:8:"required";i:0;s:11:"description";s:115:"The Paddy\'s Seals % of this sale. You can enter this OR the Margin Value. The other one will be calculated for you.";s:13:"default_value";a:1:{i:0;a:1:{s:5:"value";s:1:"0";}}}');

$s['display']['default']['type'] = 'number_decimal';

print serialize($s);

Bước 5 - Sử dụng các chuỗi được tuần tự hóa ở trên để cập nhật các cột 'dữ liệu' của bạn trong trường_config và field_config_instance

db_query('update field_config set data=\'a:7:{s:12:"translatable";s:1:"0";s:12:"entity_types";a:0:{}s:8:"settings";a:3:{s:9:"precision";s:2:"10";s:5:"scale";s:1:"2";s:17:"decimal_separator";s:1:".";}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:34:"field_data_field_margin_percentage";a:1:{s:5:"value";s:29:"field_margin_percentage_value";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:38:"field_revision_field_margin_percentage";a:1:{s:5:"value";s:29:"field_margin_percentage_value";}}}}}s:12:"foreign keys";a:0:{}s:7:"indexes";a:0:{}s:2:"id";s:3:"161";}\' where field_name=\'field_margin_percentage\'');

db_query('update field_config_instance set data=\'a:7:{s:5:"label";s:17:"Margin Percentage";s:6:"widget";a:5:{s:6:"weight";s:2:"13";s:4:"type";s:6:"number";s:6:"module";s:6:"number";s:6:"active";i:0;s:8:"settings";a:0:{}}s:8:"settings";a:7:{s:3:"min";s:1:"0";s:3:"max";s:3:"100";s:6:"prefix";s:0:"";s:6:"suffix";s:0:"";s:26:"commerce_user_profile_pane";i:0;s:35:"commerce_user_profile_pane_required";i:0;s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:14:"number_decimal";s:6:"weight";s:2:"12";s:8:"settings";a:4:{s:18:"thousand_separator";s:1:" ";s:17:"decimal_separator";s:1:".";s:5:"scale";i:0;s:13:"prefix_suffix";b:1;}s:6:"module";s:6:"number";}}s:8:"required";i:0;s:11:"description";s:115:"The Paddy-s Seals % of this sale. You can enter this OR the Margin Value. The other one will be calculated for you.";s:13:"default_value";a:1:{i:0;a:1:{s:5:"value";s:1:"0";}}}\' where field_name=\'field_margin_percentage\'');

0

Đây là cách tôi đã làm nó Drupal 7 trong một update_hook_N ().

Kế hoạch là thay đổi một trường có tên là "field_ui_civerse_salary" từ DECIMAL (10) thành DECIMAL (10,2), điều này sẽ cho phép 2 điểm thập phân cho các giá trị thay vì không có số thập phân nào cả!

/**
 * Changing Database Currenty Salary field to allow decimals.
 * Replace MYMODULE with your module's name and number N with your next incremented value.
 */
function MYMODULE_update_7001() {
  // field_ui_current_salary scale = 2 in field_config table.
  // Use your 'data' value for $new_data from 'field_config' table for your field and just change where 'scale' is from 0 to 2 (or your desired number of decimals)
  $new_data = 'a:8:{s:12:"entity_types";a:0:{}s:17:"field_permissions";a:1:{s:4:"type";i:0;}s:7:"indexes";a:0:{}s:8:"settings";a:5:{s:3:"max";d:99999999.989999995;s:3:"min";d:-99999999.989999995;s:9:"precision";i:10;s:16:"profile2_private";b:0;s:5:**"scale";i:2;**}s:12:"translatable";i:0;s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:34:"field_data_field_ui_current_salary";a:2:{s:6:"amount";s:30:"field_ui_current_salary_amount";s:8:"currency";s:32:"field_ui_current_salary_currency";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:38:"field_revision_field_ui_current_salary";a:2:{s:6:"amount";s:30:"field_ui_current_salary_amount";s:8:"currency";s:32:"field_ui_current_salary_currency";}}}}}s:12:"foreign keys";a:0:{}s:2:"id";s:3:"372";}';
  db_query('UPDATE {field_config} SET data = :new_data WHERE field_name = :salary;', array(':new_data' => $new_data, ':salary' => 'field_ui_current_salary'));

  // field_data_field_ui_current_salary and its revision copy -> DECIMAL(10,2)
  db_query("ALTER TABLE {field_data_field_ui_current_salary} MODIFY field_ui_current_salary_amount DECIMAL(10,2);");
  db_query("ALTER TABLE {field_revision_field_ui_current_salary} MODIFY field_ui_current_salary_amount DECIMAL(10,2);");

  cache_clear_all();
}

0

Câu hỏi ban đầu liên quan đến Drupal 7, nhưng tôi nghi ngờ rất nhiều người đang tự hỏi làm thế nào để làm điều này trong Drupal 8. Thật không may, hiện tại không có phương pháp nào tốt cho việc này. Tùy chọn ít tệ nhất là chỉ cần xóa trường (và bất kỳ dữ liệu nào chứa trong đó) và để Drupal tạo lại từ đầu.

Tôi đang cố gắng tìm một giải pháp tốt hơn và sẽ đăng ở đây nếu và khi có sẵn: https://www.drupal.org/node/2843108

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.