จะเปลี่ยนความยาวของการตั้งค่าฟิลด์ได้อย่างไร?


46

ฉันตั้งค่าเว็บไซต์หนึ่งครั้งเพื่อจำกัดความยาวของฟิลด์ และตอนนี้ลูกค้าต้องการเพิ่มตัวละครให้กับฟิลด์นั้นมากขึ้น

ฉันไม่สามารถเปลี่ยนขนาดสูงสุดจาก Drupal ได้เนื่องจากฉันได้รับข้อความแสดงข้อผิดพลาดต่อไปนี้:

มีข้อมูลสำหรับฟิลด์นี้ในฐานข้อมูล ไม่สามารถเปลี่ยนการตั้งค่าฟิลด์ได้อีกต่อไป

อย่างไรก็ตามจะต้องมีวิธีแก้ปัญหา ฉันจะเปลี่ยนมันในฐานข้อมูล (เขตข้อมูลถูกนำไปใช้โดยโมดูลคอลเลกชันฟิลด์ )


คุณบอกเราได้ไหมว่า Drupal และ CCK รุ่นใด นอกจากนี้โมดูล contrib CCK ใด ๆ
แพทริค

รุ่น Drupal คือ 7
Ek Kosmos

และคุณไม่สามารถแก้ไขได้ในส่วนจัดการประเภทเนื้อหา คุณควรจะสามารถแก้ไขได้ทุกเมื่อ อาจให้คำเตือน แต่ก็ควรอนุญาต นี่อาจเป็นข้อผิดพลาด / ข้อ จำกัด ในโมดูลการรวบรวมฟิลด์
แพทริค

คุณเคยลองใช้กลุ่มฟิลด์หรือไม่? ตอนนี้คุณสามารถทำสิ่งต่าง ๆ เช่นการทำสำเนากลุ่มที่คุณไม่สามารถทำได้มาก่อน
แพทริค

ฉันไม่สามารถแก้ไขได้ภายใต้หัวข้อจัดการประเภทเนื้อหา! นี่คือประเด็น Drupal อย่าให้ฉันทำ
Ek Kosmos

คำตอบ:


89

วิธีแก้ปัญหา Dylan Tack นั้นง่ายที่สุด แต่โดยส่วนตัวแล้วฉันสนุกกับการสำรวจวอร์ดด้านในของฐานข้อมูลของ Drupal เพื่อดูว่าการจัดการต่างๆ

ดังนั้นสมมติว่าคุณมีฟิลด์ข้อความที่ชื่อเครื่องคือ field_text 10 ตัวอักษรที่คุณต้องการเพิ่มขึ้นเป็น 25:

  • ข้อมูลจะถูกเก็บไว้ในสองตาราง: field_data_field_text และ field_revision_field_text
  • คำจำกัดความถูกเก็บไว้ใน field_config สำหรับข้อมูลหน่วยเก็บข้อมูลและ field_config_instance สำหรับแต่ละอินสแตนซ์ของฟิลด์นี้ (สิ่งต่างๆเช่นป้ายกำกับ)

ทีนี้ลองทำศัลยกรรมหัวใจเล็กน้อย

  1. แก้ไขนิยามคอลัมน์ตารางข้อมูล:

    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. เปลี่ยนคอลัมน์ความหมายอันนี้ยุ่งยากมากเพราะมันถูกเก็บไว้ในBLOBแต่นั่นไม่ใช่สิ่งที่จะหยุดคุณสำหรับการทำเช่นนี้

    • ผ่าความกล้าของสิ่งBLOBนี้:

    SELECT CAST(`data` AS CHAR(10000) CHARACTER SET utf8) 
    FROM `field_config` WHERE field_name = 'field_text';
    • สิ่งนี้จะให้สิ่งที่คุณต้องการ:

    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...
    • นี่คืออาร์เรย์PHP ต่อเนื่องส่วนที่น่าสนใจคือs:10:"max_length";s:2:"10";นี่หมายความว่าอาร์เรย์นี้มีคุณสมบัติชื่อmax_length(ซึ่งชื่อเป็นสตริง 10 ตัวอักษร - ดังนั้น "s") ซึ่งค่าคือ 10 (ซึ่งเป็นสตริงยาว 2 ตัวอักษร) มันค่อนข้างง่ายใช่มั้ย

    • การเปลี่ยนค่าของมันเป็นเรื่องง่ายเหมือนการเปลี่ยนส่วนหนึ่งเกิดจากs:2:"10" ระวัง:ถ้าค่าใหม่ของคุณยาวคุณต้องดัดแปลงส่วน "s" เช่นการใส่ 100 จะเท่ากับ 100 ความยาวเท่ากับ 3s:2:"25"s:3:"100"

    • ลองใส่ค่าใหม่นี้ในฐานข้อมูลอย่าลืมเก็บสตริงทั้งหมดไว้

    UPDATE `field_config` 
    SET data = 'a:7:{...a:2:{s:10:"max_length";s:2:"25";...}'
    WHERE `field_name` = 'field_text'
    • ล้างแคชของคุณ
  3. ???

  4. กำไร!

อย่างไรก็ตาม PhpMyAdmin มีการตั้งค่าบางอย่างเพื่อให้สามารถแก้ไขคอลัมน์ BLOB โดยตรงได้แต่ทำไมจึงเป็นเรื่องง่าย

PS: สิ่งนี้สามารถช่วยชีวิตคุณได้เมื่อใส่รหัส PHP บางส่วนในมุมมองและรับ WSOD เนื่องจากข้อผิดพลาดในรหัสของคุณ


ว่าคำสั่ง SQL แรกที่ควรจะพูดไม่ได้ALTER TABLE SELECT TABLEนอกจากนี้คุณสามารถทำให้มันสะอาดขึ้นเช่น: ALTER TABLE field_data_field_text MODIFY field_text_value... (แก้ไขเป็นเหมือนการเปลี่ยนแปลงเมื่อคุณไม่ต้องการเปลี่ยนชื่อและคุณทำไม่ได้)
artfulrobot

4
ขอบคุณสำหรับสิ่งนี้. ฉันหวังว่าฉันจะมีมากกว่าหนึ่ง upvote ให้
BC01

1
โพสต์นี้ใช้ Schema API ของ Drupal เพื่อให้ได้วิธีการเดียวกัน: up2technology.com/blog/converting-drupal-fields
Juampy NR

2
หากคุณไม่รังเกียจที่จะส่งข้อมูลต่อเนื่องของคุณไปยัง internets ฉันพบว่าเครื่องมือนี้เหมาะสำหรับการแก้ไข: pines.sourceforge.net/phpserialeditor.php
Pete

หากคุณได้รับข้อผิดพลาดเกี่ยวกับ 'CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL' คุณสามารถใช้ 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));
}

เช่นนี้แก้ไขมากที่สุดเพราะมันไม่ได้ขึ้นอยู่กับการแฮกเกอร์ฐานข้อมูลด้วยตนเอง ...
areynolds

9

สิ่งนี้ดูเหมือนจะเป็นข้อ จำกัด ของโมดูลข้อความปัจจุบัน text_field_settings_form ()มีความคิดเห็นนี้: " @todo : ถ้า $ has_data เพิ่มตัวจัดการตรวจสอบความถูกต้องที่อนุญาต max_length เท่านั้นที่จะเพิ่ม"

คุณสามารถแสดงความคิดเห็น'#disabled' => $has_dataในโมดูล / ฟิลด์ / modules / text / text.module ประมาณบรรทัด 77

ฉันไม่สามารถหาปัญหาที่มีอยู่เฉพาะกรณีนี้ แต่คุณอาจจะพูดถึงมันใน# 372330


2
ขอบคุณสำหรับคำตอบ. ฉันมีความคิดเห็นบรรทัดและตอนนี้ฉันสามารถปรับเปลี่ยนรูปแบบค่าเขตข้อมูล แต่ฉันได้รับข้อผิดพลาดดังต่อไปนี้หลังจาก sumbit:Attempt to update field Serial No failed: field_sql_storage cannot change the schema for an existing field with data..
เอก Kosmos

เกี่ยวกับการกระทำเรื่อง drupal โปรดดำเนินการต่อไป
Ek Kosmos

1
ฉันไม่สามารถทำงานนี้ได้ หลังจากแสดงความคิดเห็นในบรรทัดนั้นฉันยังคงพบข้อผิดพลาด MYSQL ที่ ALTER TABLE ล้มเหลว
jchwebdev

ถ้าคุณได้รับFieldUpdateForbiddenException: cannot change the schema for an existing field with dataคุณยังต้องแสดงความคิดเห็นออก L282 modules/field/modules/field_sql_storage/field_sql_storage.moduleบน
dieuwe

ความคิดเห็นของ @ dieuwe ผิด ไฟล์นั้นไม่มีอยู่ใน D8 รุ่นล่าสุด (ถ้าเคยมี) คุณต้องคอมเม้นต์สองบรรทัดในการcore/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.phpโยนข้อยกเว้นด้วยข้อความ "ที่เก็บข้อมูล SQL ไม่สามารถเปลี่ยนสคีมาสำหรับเขตข้อมูลที่มีอยู่" เกี่ยวกับสาย 1312 และ 1403
Dalin

6

Drupal 7

เมื่อสร้างฟิลด์ข้อความใน Drupal 7 คุณต้องเลือกความยาวสูงสุดสำหรับข้อมูลของคุณ ทันทีที่คุณสร้างข้อมูลใด ๆ สำหรับฟิลด์นี้ความยาวสูงสุดจะไม่เปลี่ยนรูปในการตั้งค่าฟิลด์ Drupal

เป็นที่เข้าใจได้ว่าสิ่งนี้จะถูกปิดการใช้งานเพื่อลดความยาวสูงสุดเนื่องจากอาจทำให้ข้อมูลสูญหายได้อย่างไรก็ตามควรเพิ่มความยาวสูงสุดสำหรับฟิลด์ใดก็ได้ สิ่งที่ต้องทำในรหัสโมดูลข้อความ Drupal 7 แสดงให้เห็นว่าสิ่งนี้มีจุดมุ่งหมาย แต่ไม่เคยประสบความสำเร็จ

3 สิ่งที่ต้องเกิดขึ้น:

  1. เปลี่ยนความยาว VARCHAR ของคอลัมน์ค่าในตาราง field_data_ {fieldname}
  2. เปลี่ยนความยาว VARCHAR ของคอลัมน์ค่าในตาราง field_revision_ {fieldname}
  3. อัพเดตการกำหนดค่าของเขตข้อมูลเพื่อให้สะท้อนถึงการตั้งค่าความยาวสูงสุดใหม่ฟังก์ชันต่อไปนี้ทำตามขั้นตอนทั้ง 3 ขั้นตอนเหล่านี้และใช้พารามิเตอร์ง่าย ๆ 2 ตัวรวมถึงชื่อของเขตข้อมูลและความยาวสูงสุดใหม่
/**
 * 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();
}

เมื่อฟังก์ชั่นนี้มีอยู่ในไฟล์ติดตั้งแบบกำหนดเองของคุณคุณสามารถสร้างฟังก์ชั่นอัพเดทฐานข้อมูลใหม่ที่ใช้ฟังก์ชั่นใหม่นี้เพื่อทำการเปลี่ยนแปลงที่คุณต้องการ

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

ที่มา: http://nathan.rambeck.org/blog/42-modify-drupal-7-text-field-maximum-length


Drupal 8

นี่คือเวอร์ชั่นของฟังก์ชั่นเดียวกันที่เสนอโดย@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
เราใช้เมธอด drupal 8 นี้ในโครงการและพบปัญหาซึ่งเมื่อคุณรันdrush updb --entity-updatesฟิลด์ที่เราวิ่งผ่านฟังก์ชั่นนี้จะถูกทำเครื่องหมายว่าต้องการการอัปเดต จากนั้นจะพยายามอัปเดตฟิลด์สคีมาอีกครั้งใน mysql สำหรับเราแล้วสิ่งนี้จะล้มเหลวเนื่องจากมีข้อมูลภาคสนามอยู่ในนั้น นี่เป็นการป้องกันไม่ให้งานการอัพเดทอื่น ๆ ทำงาน
leon.nk

เรื่องย่อสั้น ๆ อาจปลอดภัยกว่าในการสร้างเขตข้อมูลใหม่และย้ายข้อมูลข้าม
leon.nk

3

ลองสิ่งนี้ ... นี่จะอัปเดตชนิดข้อมูลของฟิลด์จาก TEXT เป็น LONG_TEXT และอัปเดตmax_lengthจากความยาวข้อความเป็น 4000 ถึงสูงสุด ... หวังว่านี่จะช่วยได้

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. ใส่เครื่องหมายคอมเม้นต์สองบรรทัดในcore/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchem‌​a.phpข้อยกเว้นที่มีข้อความ "ที่เก็บข้อมูล SQL ไม่สามารถเปลี่ยนสคีมาสำหรับเขตข้อมูลที่มีอยู่" เกี่ยวกับสาย 1312 และ 1403
  2. /admin/config/development/configuration/single/exportในเบราว์เซอร์ของคุณเพื่อนำทาง ประเภทการกำหนดค่าคือ "Field Storage" และเลือกฟิลด์ที่เป็นปัญหา คัดลอกการกำหนดค่า
  3. /admin/config/development/configuration/single/importนำทางไปยัง . ประเภทการกำหนดค่าคือ "Field Storage" วางการกำหนดค่า เปลี่ยนความยาว
  4. ส่งแบบฟอร์ม

หมายเหตุ (ตามที่คุณอาจทราบแล้ว) หากคุณตัดทอนความยาวข้อมูลที่มีอยู่จะถูกตัดทอน


สิ่งนี้ได้ผลเหมือนมนต์เสน่ห์ ตั้งแต่ Drupal 8.5.3 บรรทัดคือ 1505-1507 ในฟังก์ชันป้องกันที่ได้รับการอัพเดต updateDedicatedTableSchema และ 1596-1598 ในฟังก์ชันป้องกันที่ได้รับการอัพเดต อย่าลืมเปลี่ยนกลับเมื่อเสร็จแล้ว! ขอขอบคุณ.
HongPong

ฉันลองวิธีนี้เป็นครั้งแรก ฉันพยายามแก้ไขเขตข้อมูลย่อหน้า มันใช้งานได้ แต่อย่างไรก็ตามจำเป็นต้องเปลี่ยนแปลง ALTER ตารางที่เกี่ยวข้อง
Yaazkal

@ Yaazkal อืมนั่นไม่ใช่ประสบการณ์ของฉัน คุณพยายามยืดหรือย่นสนามให้สั้นลงหรือไม่?
Dalin

@Dalin ยาวจาก 255 ถึง 510 ใช้ D 8.5.5 และย่อหน้า 1.3
Yaazkal

1

ใน Drupal 7 ฉันทำการแก้ไข 2 ตารางใน phpmyadmin และรีเฟรชแคช

  1. "field_data_field_lorem": เปลี่ยน "field_lorem_value" เป็น "longtext"
  2. "field_config": เปลี่ยน "type" เป็น "text_long"

คุณส่งสิ่งนี้เป็นแพตช์ถึง D7 หรือไม่? หากนี่เป็นปัญหาอย่างแท้จริงคุณควรออก patch ให้พวกเขาเพื่อแก้ไขปัญหานี้ในรหัสหลัก
แพทริค

ฉันได้เปลี่ยนค่าขนาดฟิลด์จาก phpmyadmin (จาก 10 เป็น 25 ของประเภท VARCHAR) และรีเฟรชแคชอย่างไรก็ตามไม่ทำงาน ในฐานข้อมูล ramarned VARCHAR (25) แต่ใน Drupal ฟิลด์นั้นมีขนาดสูงสุดเท่าเดิมก่อนหน้า 10 บางทีอาจมีการตั้งค่าฟิลด์ที่ซ่อนอยู่บ้างไหม
Ek Kosmos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.