Bagaimana cara mengubah panjang pengaturan bidang?

46

Saya telah menetapkan batas panjang untuk sebuah situs web pada suatu waktu. Dan sekarang klien ingin menempatkan lebih banyak karakter ke bidang itu.

Saya tidak dapat mengubah ukuran maksimum dari Drupal karena saya mendapatkan pesan kesalahan berikut:

Ada data untuk bidang ini dalam database. Pengaturan bidang tidak lagi dapat diubah.

Namun harus ada solusinya. Haruskah saya mengubahnya di basis data (bidang ini adalah salah satu yang diimplementasikan oleh modul Koleksi lapangan )?

Ek Kosmos
sumber
Bisakah Anda memberi tahu kami versi Drupal dan CCK apa? Juga ada modul contrib CCK?
Patrick
Versi Drupal adalah 7.
Ek Kosmos
Dan Anda tidak dapat memodifikasinya di bawah bagian isian jenis pengelolaan? Anda harus dapat memodifikasinya kapan saja. Mungkin memberi Anda peringatan, tetapi harus tetap mengizinkannya. Ini mungkin bug / batasan dalam modul koleksi lapangan.
Patrick
Sudahkah Anda mencoba menggunakan grup bidang? Anda sekarang dapat melakukan hal-hal seperti duplikasi grup yang sebelumnya tidak dapat Anda lakukan.
Patrick
Saya tidak dapat memodifikasinya di bawah bagian isian jenis pengelolaan! Ini intinya. Drupal jangan biarkan aku melakukannya.
Ek Kosmos

Jawaban:

89

Solusi Dylan Tack adalah yang termudah, tetapi secara pribadi saya menikmati menjelajahi bagian dalam basis data Drupal untuk melihat bagaimana segala sesuatu dikelola di sana.

Jadi, anggap Anda memiliki bidang teks yang nama mesinnya adalah field_text dengan 10 karakter yang ingin Anda kembangkan menjadi 25:

  • data akan disimpan dalam dua tabel: field_data_field_text dan field_revision_field_text
  • definisi disimpan di field_config untuk data penyimpanan, dan field_config_instance untuk setiap instance bidang ini (hal-hal seperti label).

Sekarang mari kita lakukan operasi jantung kecil.

  1. Ubah definisi kolom tabel data:

    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. Ubah kolom definisi , yang ini sangat sulit karena disimpan dalam BLOB , tetapi itu bukan sesuatu yang akan menghentikan Anda untuk melakukan ini.

    • Membedah nyali hal Gumpalan ini :

    SELECT CAST(`data` AS CHAR(10000) CHARACTER SET utf8) 
    FROM `field_config` WHERE field_name = 'field_text';
    • Ini akan memberi Anda sesuatu seperti:

    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...
    • Ini adalah array serial PHP , bagian yang menarik adalah s:10:"max_length";s:2:"10";, ini berarti array ini memiliki properti bernama max_length(yang namanya string 10 karakter - maka "s") yang nilainya 10 (yang merupakan string panjang 2 karakter). Cukup mudah, bukan?

    • Mengubah nilainya semudah mengganti s:2:"10"bagian dengan s:2:"25". Hati-hati: jika nilai baru Anda lebih lama, Anda harus menyesuaikan bagian "s", misalnya menempatkan 100 akan s:3:"100"sama panjang 100 dengan 3.

    • Mari kita masukkan nilai baru ini ke dalam DB, jangan lupa untuk menyimpan seluruh string.

    UPDATE `field_config` 
    SET data = 'a:7:{...a:2:{s:10:"max_length";s:2:"25";...}'
    WHERE `field_name` = 'field_text'
    • Siram cache Anda.
  3. ???

  4. KEUNTUNGAN!

Ngomong-ngomong, PhpMyAdmin memiliki beberapa pengaturan untuk memungkinkan modifikasi langsung pada kolom BLOB , tetapi mengapa melakukannya dengan mudah?

PS: Ini juga dapat menyelamatkan hidup Anda ketika menempatkan beberapa kode PHP dalam pandangan dan mendapatkan WSOD karena kesalahan dalam kode Anda.

tostinni
sumber
Pernyataan SQL pertama harus mengatakan ALTER TABLEtidak SELECT TABLE. Juga, Anda dapat membuatnya lebih bersih seperti: ALTER TABLE field_data_field_text MODIFY field_text_value... (MODIFY seperti CHANGE ketika Anda tidak ingin mengubah nama . Dan Anda tidak.)
artfulrobot
4
Terima kasih untuk ini. Saya berharap saya memiliki lebih dari satu suara untuk diberikan.
BC01
1
Posting ini menggunakan Skema API Drupal untuk mencapai pendekatan yang sama: up2technology.com/blog/converting-drupal-fields
Juampy NR
2
Jika Anda tidak keberatan mengirim data bersambung ke internet, saya menemukan alat ini, bagus untuk mengedit: pines.sourceforge.net/phpserialeditor.php
Pete
Jika Anda mendapatkan kesalahan tentang 'SET KARAKTER utf8 COLLATE utf8_general_ci NULL DEFAULT NULL', Anda dapat menggunakan 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));
}
Kevin Thompson
sumber
Seperti memperbaiki ini paling karena itu tidak bergantung pada hackery DB manual ... memiliki solusi yang dapat direplikasi melalui hook_update_N sangat penting!
areynolds
9

Ini tampaknya menjadi batasan modul teks saat ini. text_field_settings_form () memiliki komentar ini: " @todo : Jika $ has_data, tambahkan validator handler yang hanya memperbolehkan max_length bertambah.".

Sebagai solusi sementara, Anda dapat berkomentar '#disabled' => $has_datadi modul / bidang / modul / teks / text.module, sekitar baris 77.

Saya tidak dapat menemukan masalah yang ada untuk kasus khusus ini, tetapi Anda mungkin menyebutkannya di # 372330 .

Dylan Tack
sumber
2
Terima kasih atas jawaban anda. Saya telah berkomentar baris dan sekarang saya dapat mengubah nilai dari bidang, namun saya mendapatkan kesalahan berikut setelah sumbit:Attempt to update field Serial No failed: field_sql_storage cannot change the schema for an existing field with data..
Ek Kosmos
Mengenai masalah drupal, silakan lanjutkan dan lakukan.
Ek Kosmos
1
Saya tidak bisa melakukan ini. Setelah mengomentari baris itu, saya masih mendapat kesalahan MYSQL yang ALTER TABLE gagal.
jchwebdev
Jika Anda mendapatkan FieldUpdateForbiddenException: cannot change the schema for an existing field with dataAnda juga perlu mengomentari L282 pada modules/field/modules/field_sql_storage/field_sql_storage.module.
dieuwe
Komentar @ dieuwe salah. File itu tidak ada di versi terbaru D8 (jika pernah melakukannya). Anda perlu mengomentari dua baris dalam core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.phppengecualian lemparan dengan teks "Penyimpanan SQL tidak dapat mengubah skema untuk bidang yang ada". Tentang baris 1312 dan 1403.
Dalin
6

Drupal 7

Saat membuat bidang teks dalam Drupal 7, Anda harus memilih panjang maksimum untuk data Anda. Segera setelah Anda membuat data apa pun untuk bidang ini, panjang maksimum menjadi tidak berubah dalam pengaturan bidang Drupal.

Dapat dimengerti bahwa ini akan dinonaktifkan untuk mengurangi panjang maksimum karena bisa mengakibatkan hilangnya data, namun, harus mungkin untuk menambah panjang maksimum untuk bidang apa pun. Sebuah todo dalam kode modul Drupal 7 Teks menunjukkan ini dimaksudkan tetapi tidak pernah dilakukan.

3 hal yang perlu terjadi:

  1. Ubah panjang VARCHAR dari kolom nilai di tabel field_data_ {fieldname}
  2. Ubah panjang VARCHAR dari kolom nilai di tabel field_revision_ {fieldname}
  3. Perbarui konfigurasi bidang untuk mencerminkan pengaturan panjang maks baru. Fungsi berikut menyelesaikan 3 langkah ini dan mengambil 2 parameter mudah termasuk nama bidang dan panjang maksimum baru.
/**
 * 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();
}

Setelah fungsi ini tersedia di file instal kustom Anda, Anda dapat membuat fungsi pembaruan basis data baru yang menggunakan fungsi baru ini untuk membuat perubahan yang diperlukan.

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

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


Drupal 8

Berikut adalah versi dari fungsi yang sama yang diusulkan oleh @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
    );
  }
}
kenorb
sumber
1
Kami menggunakan metode 8 drupal ini pada sebuah proyek dan mengalami masalah di mana ketika Anda menjalankan drush updb --entity-updatesbidang yang kami jalankan melalui fungsi ini akan ditandai sebagai membutuhkan pembaruan. Kemudian akan mencoba untuk memperbarui skema bidang lagi di mysql. Bagi kami ini akan gagal karena sudah ada data lapangan di sana. Ini mencegah tugas pembaruan lainnya berjalan.
leon.nk
Singkatnya, mungkin lebih aman untuk membuat bidang baru dan memigrasikan data.
leon.nk
3

Coba ini ... ini akan memperbarui tipe data bidang dari TEXT ke LONG_TEXT dan memperbarui max_lengthdari 4000 hingga maks panjang teks ... harap ini membantu.

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);    
  }
}
Harold
sumber
3

D8

  1. Mengomentari dua baris dalam core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchem‌​a.phppengecualian melempar dengan teks "Penyimpanan SQL tidak dapat mengubah skema untuk bidang yang ada". Tentang garis 1312 dan 1403.
  2. Di browser Anda, navigasikan ke /admin/config/development/configuration/single/export. Jenis konfigurasi adalah "Bidang Penyimpanan", dan pilih bidang yang dimaksud. Salin konfigurasinya.
  3. Arahkan ke /admin/config/development/configuration/single/import. . Jenis konfigurasi adalah "Bidang Penyimpanan". Rekatkan konfigurasi. Ubah panjangnya.
  4. Kirimkan formulir.

Catatan (seperti yang mungkin sudah Anda ketahui), jika Anda mempersingkat panjangnya, maka data yang ada akan terpotong.

Dalin
sumber
Ini bekerja seperti pesona. Pada Drupal 8.5.3 baris-barisnya adalah 1505-1507 dalam pembaruan fungsi terlindungiDedicatedTableSchema dan 1596-1598 dalam pembaruan fungsi terlindungiSharedTableSchema. Pastikan untuk kembali setelah selesai! Terima kasih.
HongPong
Saya pertama kali mencoba pendekatan ini. Saya mencoba mengubah bidang paragraf. Ini bekerja tetapi tetap wajib mengubah tabel yang sesuai.
Yaazkal
@Yaazkal Hmmm, itu bukan pengalaman saya. Apakah Anda mencoba memperpanjang atau mempersingkat bidang?
Dalin
@Dalin memanjang, dari 255 menjadi 510. Menggunakan D 8.5.5 dan Paragraf 1.3
Yaazkal
1

Di Drupal 7, saya membuat modifikasi ke 2 tabel di phpmyadmin, dan menyegarkan cache.

  1. "field_data_field_lorem": berubah "field_lorem_value" menjadi "longtext"
  2. "field_config": diubah "ketik" menjadi "text_long"
Jill
sumber
Apakah Anda mengirimkan ini sebagai tambalan ke D7? Jika ini benar-benar masalah maka Anda harus benar-benar mengeluarkan tambalan kepada mereka untuk menyelesaikan masalah ini dalam kode inti.
Patrick
Saya telah mengubah nilai ukuran bidang saya dari phpmyadmin (dari 10 menjadi 25 jenis VARCHAR), dan menyegarkan cache, namun tidak berfungsi. Dalam basis data yang dinamai VARCHAR (25) tetapi dalam Drupal, bidang berada pada nilai ukuran maksimum yang sama seperti sebelumnya 10. Mungkin ada beberapa pengaturan bidang tersembunyi?
Ek Kosmos