Làm cách nào để thay đổi độ dài của cài đặt trường?


46

Tôi đã đặt một lần cho một trang web một giới hạn chiều dài cho một lĩnh vực. Và bây giờ khách hàng muốn đưa thêm nhân vật vào lĩnh vực đó.

Tôi không thể thay đổi kích thước tối đa từ Drupal vì tôi nhận được thông báo lỗi sau:

Có dữ liệu cho lĩnh vực này trong cơ sở dữ liệu. Các thiết lập trường không còn có thể thay đổi.

Tuy nhiên phải có một giải pháp. Tôi có nên thay đổi nó trong cơ sở dữ liệu không (trường được thực hiện bởi mô-đun Bộ sưu tập trường )?


Bạn có thể cho chúng tôi biết phiên bản nào của Drupal và CCK không? Ngoài ra bất kỳ mô-đun đóng góp CCK?
Patrick

Phiên bản Drupal là 7.
Ek Kosmos

Và bạn không thể sửa đổi nó trong phần quản lý loại nội dung? Bạn sẽ có thể sửa đổi nó bất cứ lúc nào. Nó có thể cho bạn một cảnh báo, nhưng nó vẫn sẽ cho phép nó. Đây có thể là lỗi / giới hạn trong mô-đun bộ sưu tập trường.
Patrick

Bạn đã thử sử dụng các nhóm lĩnh vực? Bây giờ bạn có thể làm những việc như sao chép nhóm mà trước đây bạn không thể làm được.
Patrick

Tôi không thể sửa đổi nó trong phần quản lý loại nội dung! Đây là điểm. Drupal đừng để tôi làm điều đó.
Ek Kosmos

Câu trả lời:


89

Giải pháp Dylan Tack là dễ nhất, nhưng cá nhân tôi thích khám phá các phường bên trong cơ sở dữ liệu của Drupal để xem mọi thứ được quản lý ở dưới đó như thế nào.

Vì vậy, giả sử bạn có một trường văn bản có tên máy là trường văn bản gồm 10 ký tự bạn muốn tăng lên 25:

  • dữ liệu sẽ được lưu trữ trong hai bảng: field_data_fieldigin và field_Vvision_field bản
  • định nghĩa được lưu trữ trong field_config cho dữ liệu lưu trữ và field_config_instance cho từng phiên bản của trường này (thứ như nhãn).

Bây giờ chúng ta hãy làm một chút phẫu thuật tim.

  1. Thay đổi các định nghĩa cột bảng dữ liệu:

    ALTER TABLE `field_data_field_text` 
    CHANGE `field_text_value` `field_text_value` VARCHAR( 25 ) 
    CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
    
    ALTER TABLE `field_revision_field_text` 
    CHANGE `field_text_value` `field_text_value` VARCHAR( 25 ) 
    CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
  2. Thay đổi cột định nghĩa , cái này rất khó vì nó được lưu trong BLOB , nhưng đó không phải là thứ sẽ ngăn bạn làm điều này.

    • Phân tích can đảm của điều BLOB này:

    SELECT CAST(`data` AS CHAR(10000) CHARACTER SET utf8) 
    FROM `field_config` WHERE field_name = 'field_text';
    • Điều này sẽ cung cấp cho bạn một cái gì đó như:

    a:7:{s:12:"translatable";s:1:"1";s:12:"entity_types";a:0:{}s:8:"settings";a:2:
        {s:10:"max_length";s:2:"10";s:17:"field_permissions";a:5:
        //a lot more stuff...
    • Đây là một mảng được tuần tự hóa PHP , phần thú vị là s:10:"max_length";s:2:"10";, điều này có nghĩa là mảng này có một thuộc tính có tên max_length(tên là một chuỗi 10 ký tự - do đó "s") có giá trị là 10 (là một chuỗi dài 2 ký tự). Nó khá dễ, phải không?

    • Thay đổi giá trị của nó dễ dàng như thay thế s:2:"10"một phần bằng s:2:"25". Hãy cẩn thận: nếu giá trị mới của bạn dài hơn, bạn phải điều chỉnh phần "s", ví dụ: đặt 100 sẽ s:3:"100"là 100 chiều dài là 3.

    • Hãy đặt lại giá trị mới này trong DB, đừng quên giữ toàn bộ chuỗi.

    UPDATE `field_config` 
    SET data = 'a:7:{...a:2:{s:10:"max_length";s:2:"25";...}'
    WHERE `field_name` = 'field_text'
    • Xóa bộ nhớ cache của bạn.
  3. ???

  4. LỢI NHUẬN!

Nhân tiện, PhpMyAdmin có một số cài đặt để cho phép sửa đổi trực tiếp các cột BLOB , nhưng tại sao lại đi theo cách dễ dàng?

PS: Điều này cũng có thể cứu mạng bạn khi đưa một số mã PHP vào các khung nhìn và nhận WSOD do lỗi trong mã của bạn.


Đó là câu lệnh SQL đầu tiên nên nói là ALTER TABLEkhông SELECT TABLE. Ngoài ra, bạn có thể làm cho nó sạch hơn như: ALTER TABLE field_data_field_text MODIFY field_text_value... (MODIFY giống như THAY ĐỔI khi bạn không muốn thay đổi tên . Và bạn không.)
artfulrobot 2/212

4
Cảm ơn vì điều đó. Tôi ước tôi có nhiều hơn một upvote để cung cấp.
BC01

1
Bài đăng này sử dụng API Schema của Drupal để đạt được cùng một cách tiếp cận: up2t Technology.com/blog/converting-drupal-fields
Juampy NR

2
Nếu bạn không ngại gửi dữ liệu tuần tự của mình đến các mạng nội bộ, tôi đã tìm thấy công cụ này, rất phù hợp để chỉnh sửa: pines.sourceforge.net/phpserialeditor.php
Pete

Nếu bạn gặp lỗi về 'CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL', bạn có thể sử dụng PhpMyAdmin.
tog22

19
function mymodule_update_7100() {
  $items = array();
  _field_maxlength_fix('field_name');
  return $items;
}

function _field_maxlength_fix($field_name, $maxlength = 255) {
  _alter_field_table($field_name, $maxlength);
  $data = _get_field_data($field_name);
  $data = _fix_field_data($data, $maxlength);
  _update_field_config($data, $field_name);
}

function _alter_field_table($field_name, $maxlength) {
  db_query("ALTER TABLE field_data_".$field_name." CHANGE ".$field_name."_value ".$field_name."_value VARCHAR( ".$maxlength." ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL");
  db_query("ALTER TABLE field_revision_".$field_name." CHANGE ".$field_name."_value ".$field_name."_value VARCHAR( ".$maxlength." ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL");
}

function _get_field_data($field_name) {
  $qry = "SELECT data FROM field_config WHERE field_name = :field_name";
  $result = db_query($qry, array(':field_name' => $field_name))->fetchObject();
  return unserialize($result->data);
}

function _fix_field_data($data, $maxlength) {
  $data['settings']['max_length'] = (string)$maxlength;
  return serialize($data);
}

function _update_field_config($data, $field_name) {
  $qry = "UPDATE field_config SET data = :data WHERE field_name = :field_name";
  db_query($qry, array(':data' => $data, ':field_name' => $field_name));
}

Giống như cách khắc phục này nhất vì nó không phụ thuộc vào hack DB thủ công ... có một giải pháp có thể nhân rộng thông qua hook_update_N là điều cần thiết!
thiệu vào

9

Điều này dường như là một hạn chế của mô-đun văn bản hiện tại. text_field_sinstall_form () có nhận xét này: " @todo : Nếu $ has_data, hãy thêm trình xử lý xác thực chỉ cho phép max_length tăng.".

Như một giải pháp tạm thời, bạn có thể nhận xét '#disabled' => $has_datatrong các mô-đun / trường / mô-đun / văn bản / text.module, xung quanh dòng 77.

Tôi không thể tìm thấy một vấn đề hiện tại cho trường hợp cụ thể này, nhưng bạn có thể đề cập đến vấn đề này trên # 372330 .


2
Cảm ơn câu trả lời của bạn. Tôi đã nhận xét dòng và bây giờ tôi có thể sửa đổi biểu mẫu giá trị của trường, tuy nhiên tôi gặp lỗi sau khi sumbit:Attempt to update field Serial No failed: field_sql_storage cannot change the schema for an existing field with data..
Ek Kosmos

Liên quan đến việc cam kết vấn đề drupal, xin vui lòng đi trước và làm điều đó.
Ek Kosmos

1
Tôi không thể làm việc này. Sau khi nhận xét dòng đó, tôi vẫn gặp lỗi MYSQL mà ALTER TABLE không thành công.
jchwebdev

Nếu bạn nhận được một FieldUpdateForbiddenException: cannot change the schema for an existing field with databạn cũng cần phải nhận xét L282 trên modules/field/modules/field_sql_storage/field_sql_storage.module.
dieuwe

Nhận xét của @ dieuwe là sai. Tập tin đó không tồn tại trong các phiên bản gần đây của D8 (nếu có). Bạn cần nhận xét hai dòng trong core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.phpđó đưa ra các ngoại lệ với văn bản "Bộ lưu trữ SQL không thể thay đổi lược đồ cho một trường hiện có". Giới thiệu về dòng 1312 và 1403.
Dalin

6

Drupal 7

Khi tạo trường văn bản trong Drupal 7, bạn phải chọn độ dài tối đa cho dữ liệu của mình. Ngay khi bạn tạo bất kỳ dữ liệu nào cho trường này, độ dài tối đa sẽ trở thành bất biến trong cài đặt trường Drupal.

Có thể hiểu rằng điều này sẽ bị vô hiệu hóa khi giảm độ dài tối đa vì nó có thể dẫn đến mất dữ liệu, tuy nhiên, có thể tăng độ dài tối đa cho bất kỳ trường nào. Một việc cần làm trong mã mô-đun Drupal 7 cho thấy điều này đã được dự định nhưng không bao giờ được thực hiện.

3 điều cần phải xảy ra:

  1. Thay đổi độ dài VARCHAR của cột giá trị trong bảng field_data_ {fieldname}
  2. Thay đổi độ dài VARCHAR của cột giá trị trong bảng field_Vvision_ {fieldname}
  3. Cập nhật cấu hình của trường để phản ánh cài đặt độ dài tối đa mới Chức năng sau đây thực hiện cả 3 bước này và có 2 tham số dễ dàng bao gồm tên của trường và độ dài tối đa mới.
/**
 * Helper function to change the max length of a text field.
 */
function MYMODULE_change_text_field_max_length($field_name, $new_length) {
  $field_table = 'field_data_' . $field_name;
  $field_revision_table = 'field_revision_' . $field_name;
  $field_column = $field_name . '_value';

  // Alter value field length in fields table.
  db_query("UPDATE `{$field_table}` SET `{$field_column}`=SUBSTR(`{$field_column}`, 0, {$new_length})");
  db_query("ALTER TABLE `{$field_table}` CHANGE `{$field_column}` `{$field_column}` VARCHAR( {$new_length} )");
  // Alter value field length in fields revision table.
  db_query("UPDATE `{$field_revision_table}` SET `{$field_column}`=SUBSTR(`{$field_column}`, 0, {$new_length})");
  db_query("ALTER TABLE `{$field_revision_table}` CHANGE `{$field_column}` `{$field_column}` VARCHAR( {$new_length} )");

  // Update field config with new max length.
  $result = db_query("SELECT CAST(`data` AS CHAR(10000) CHARACTER SET utf8) FROM `field_config` WHERE field_name = '{$field_name}'");
  $config = $result->fetchField();
  $config_array = unserialize($config);
  $config_array['settings']['max_length'] = $new_length;
  $config = serialize($config_array);
  db_update('field_config')
    ->fields(array('data' => $config))
    ->condition('field_name', $field_name)
    ->execute();
}

Khi chức năng này có sẵn trong tệp cài đặt tùy chỉnh của bạn, bạn có thể tạo một chức năng cập nhật cơ sở dữ liệu mới sử dụng chức năng mới này để thực hiện các thay đổi cần thiết của bạn.

/**
 * Change max_length of Name field
 */
function mymodule_update_7002() {
  MYMODULE_change_text_field_max_length('field_name', 50);
}

Nguồn: http://nathan.rambeck.org/blog/42-modify-drupal-7-text-field-maximum-length


Drupal 8

Đây là phiên bản của chức năng tương tự được đề xuất bởi @Christopher :

/**
 * Utility to change the max length of a text field.
 *
 * @param string $field_name
 *   Field name. 
 * @param int $new_length
 *   Field length in characters. 
 *
 * @throws \DrupalUpdateException
 */
function MYMODULE_change_text_field_max_length($field_name, $new_length) {
  // The transaction opens here. 
  $txn = db_transaction();

  try {
    // Update field content tables with new max length.
    foreach (['field_data_', 'field_revision_'] as $prefix) {
      db_query('
      ALTER TABLE {' . $prefix . $field_name . '} 
        MODIFY ' . $field_name . '_value VARCHAR( ' . $new_length . ' )
      ');
    }

    // Update field config record with new max length.
    $result = db_query("
        SELECT CAST(data AS CHAR(10000) CHARACTER SET utf8) 
        FROM {field_config} 
        WHERE field_name = :field_name
      ", [':field_name' => $field_name]
    );
    $config = $result->fetchField();
    if ($config) {
      $config_array = unserialize($config);
      $config_array['settings']['max_length'] = $new_length;
      $new_config = serialize($config_array);
      db_update('field_config')
        ->fields(['data' => $new_config])
        ->condition('field_name', $field_name)
        ->execute();
    }
  }
  catch (Exception $e) {
    // Something went wrong somewhere, so roll back now.
    $txn->rollback();
    // Allow update to be re-run when errors are fixed.
    throw new \DrupalUpdateException(
      "Failed to change $field_name field max length: " . $e->getMessage(),
      $e->getCode(), $e
    );
  }
}

1
Chúng tôi đã sử dụng phương pháp 8 drupal này trên một dự án và gặp phải các vấn đề khi bạn chạy drush updb --entity-updatescác trường mà chúng tôi chạy qua chức năng này sẽ được đánh dấu là yêu cầu cập nhật. Sau đó, nó sẽ cố gắng cập nhật lại lược đồ trường trong mysql. Đối với chúng tôi điều này sau đó sẽ thất bại vì đã có dữ liệu thực địa ở đó. Điều này đã ngăn các tác vụ cập nhật khác chạy.
leon.nk

Tóm lại, có lẽ an toàn hơn khi tạo các trường mới và di chuyển dữ liệu qua.
leon.nk

3

Hãy thử điều này ... điều này sẽ cập nhật kiểu dữ liệu trường từ TEXT thành LONG_TEXT và cập nhật max_lengthtừ 4000 đến độ dài văn bản dài ... hy vọng điều này sẽ giúp.

function my_module_update_1001(&$sandbox) {
  // Check if our field is already created.
  if (field_info_field('sample_text_field')) {
    db_query('ALTER TABLE field_data_sample_text_field CHANGE sample_text_field_value sample_text_field_value LONGTEXT');
    db_query('ALTER TABLE field_revision_sample_text_field CHANGE sample_text_field_value sample_text_field_value LONGTEXT');
    db_query("UPDATE field_config SET type = 'text_long' WHERE field_name = 'sample_text_field' ");

    $field = array(
      'field_name' => 'sample_text_field',
      'type' => 'text_long',
      'cardinality' => 1,
      'settings' => array(
         'max_length' => 0,
      ),
    );
    field_update_field($field);    
  }
}

3

D8

  1. Nhận xét hai dòng trong core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchem‌​a.phpđó ném ngoại lệ với văn bản "Bộ lưu trữ SQL không thể thay đổi lược đồ cho một trường hiện có". Về dòng 1312 và 1403.
  2. Trong trình duyệt của bạn, điều hướng đến /admin/config/development/configuration/single/export. Loại cấu hình là "Lưu trữ trường" và chọn trường được đề cập. Sao chép cấu hình.
  3. Điều hướng đến /admin/config/development/configuration/single/import. . Loại cấu hình là "Lưu trữ trường". Dán cấu hình. Thay đổi độ dài.
  4. Gửi mẫu đơn.

Lưu ý (như bạn có thể đã biết), nếu bạn rút ngắn thời lượng, thì dữ liệu hiện tại sẽ bị cắt ngắn.


Điều này làm việc như một nét duyên dáng. Kể từ Drupal 8.5.3, các dòng là 1505-1507 trong cập nhật chức năng được bảo vệDocateTableSchema và 1596-1598 trong cập nhật chức năng được bảo vệSharedTableSchema. Hãy chắc chắn để thay đổi trở lại khi nó hoàn thành! Cảm ơn bạn.
HongPong

Lần đầu tiên tôi thử phương pháp này. Tôi đang cố gắng sửa đổi một trường đoạn. Nó hoạt động nhưng dù sao thì bắt buộc phải THAY ĐỔI các bảng tương ứng.
Yaazkal

@Yaazkal Hmmm, đó không phải là kinh nghiệm của tôi. Bạn đang cố gắng kéo dài hoặc rút ngắn lĩnh vực?
Dalin

@Dalin kéo dài, từ 255 đến 510. Sử dụng D 8.5.5 và Đoạn 1.3
Yaazkal 16/07/18

1

Trong Drupal 7, tôi đã sửa đổi 2 bảng bằng phpmyadmin và làm mới bộ đệm.

  1. "field_data_field_lorem": đã thay đổi "field_lorem_value" thành "longtext"
  2. "field_config": đã thay đổi "loại" thành "text_long"

Bạn đã gửi nó dưới dạng bản vá cho D7? Nếu đây thực sự là vấn đề thì bạn nên thực sự phát hành một bản vá cho họ để giải quyết vấn đề này trong mã lõi.
Patrick

Tôi đã thay đổi giá trị kích thước trường từ phpmyadmin (từ 10 thành 25 loại VARCHAR) và làm mới bộ đệm, tuy nhiên không hoạt động. Trong cơ sở dữ liệu đã phân bổ VARCHAR (25) nhưng trong Drupal, trường có cùng giá trị kích thước tối đa như trước 10. Có thể có một số cài đặt trường ẩn?
Ek Kosmos
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.