Як змінити довжину параметрів поля?


46

Я один раз встановив на веб-сайті обмеження довжини поля. А тепер клієнт хоче поставити більше символів у це поле.

Я не можу змінити максимальний розмір від Drupal, оскільки я отримую таке повідомлення про помилку:

У базі даних є це поле. Налаштування поля більше не можна змінювати.

Однак рішення повинно бути. Чи повинен я змінити його в базі даних (поле реалізується модулем Field-collection )?


Чи можете ви сказати нам, яка версія Drupal та CCK? Також будь-які модулі внеску CCK?
Патрік

Версія Drupal - 7.
Ек Космос

І ви не можете змінити його в розділі полів управління вмістом типу вмісту? Ви можете мати змогу змінити його в будь-якій точці. Це може надати вам попередження, але все ж слід це дозволити. Це може бути помилка / обмеження в модулі колекції полів.
Патрік

Ви намагалися використовувати польові групи? Тепер ви можете робити такі речі, як групове дублювання, чого ви раніше не могли.
Патрік

Я не можу його змінити в розділі полів управління вмістом типу вмісту! У цьому справа. Друпал не дай мені це зробити.
Ек Космос

Відповіді:


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 (що являє собою довгий рядок на два символи). Це досить просто, чи не так?

    • Змінити його значення так само просто, як замінити s:2:"10"деталь на s:2:"25". Будьте уважні: якщо ваше нове значення довше, вам доведеться адаптувати "s" частину, наприклад, ставити 100 буде s:3:"100"як 100, то довжина 3.

    • Давайте повернемо це нове значення ще в БД, не забудьте зберегти цілий рядок.

    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
Дякую за це Я б хотів, щоб я мав більше одного рішення.
BC01

1
Ця публікація використовує API схеми Drupal для досягнення того ж підходу: up2technology.com/blog/converting-drupal-fields
Juampy NR,

2
Якщо ви не проти надсилати свої серіалізовані дані до мереж
Піт

Якщо ви отримаєте помилку про "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));
}

Найбільше подобається це виправлення, оскільки воно не покладається на ручне хакерство БД ... наявність копіюваного рішення за допомогою ho_update_N має важливе значення!
areynolds

9

Це видається обмеженням поточного текстового модуля. text_field_settings_form () має цей коментар: " @todo : Якщо $ has_data, додайте перевірений обробник, який дозволяє збільшити лише довжину max_length."

Як тимчасове вирішення, ви можете прокоментувати '#disabled' => $has_dataв модулях / поле / модулі / текст / text.module, біля рядка 77.

Я не зміг знайти існуючу проблему для цього конкретного випадку, але ви можете згадати її на # 372330 .


2
Дякую за вашу відповідь. Я прокоментував рядок, і тепер я можу змінити значення з поля, однак після сумбіту я отримую таку помилку:Attempt to update field Serial No failed: field_sql_storage cannot change the schema for an existing field with data..
Ек Космос

Щодо вчинення проблеми з друпалом, будь ласка, продовжуйте це робити.
Ек Космос

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.
Далін

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


Друпал 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. Тип конфігурації - "Поле зберігання" та виберіть поле, про яке йдеться. Скопіюйте конфігурацію.
  3. Перейдіть до /admin/config/development/configuration/single/import. . Тип конфігурації - "Поле зберігання". Вставте конфігурацію. Зміна довжини.
  4. Надішліть форму.

Зауважте (як ви, напевно, вже знаєте), якщо скоротити довжину, то наявні дані будуть усічені.


Це спрацювало як шарм. Станом на Drupal 8.5.3 рядки складаються з 1505-1507 у захищеній функції updateDedicatedTableSchema та 1596-1598 у захищеній функції updateSharedTableSchema. Не забудьте змінити назад, коли це буде зроблено! Дякую.
Гонконг

Я вперше спробував такий підхід. Я намагаюся змінити поле абзацу. Він працює, але в будь-якому випадку є обов'язковим для ВИНАХОДЖЕННЯ відповідних таблиць.
Яаскал

@Yaazkal Гммм, це не був мій досвід. Ви намагаєтесь подовжити чи скоротити поле?
Далін

@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? Якщо це справді проблема, то вам дійсно слід видати їм патч, щоб вирішити цю проблему в основному коді.
Патрік

Я змінив своє значення розміру поля з phpmyadmin (від 10 до 25 типу VARCHAR) і оновив кеш, однак не працює. У базі даних VARCHAR (25), яка перебуває в базі даних, але в Drupal, поле має таке ж максимальне значення розміру, як і раніше 10. Можливо, є якесь приховане налаштування поля?
Ек Космос
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.