如何更改字段设置的长度?


46

我曾经为网站设置了一个字段的最大限制。现在,客户希望在该字段中添加更多字符。

我无法从Drupal更改最大大小,因为我收到以下错误消息:

数据库中有此字段的数据。字段设置不能再更改。

但是,必须有一个解决方案。我是否应该在数据库中更改它(该字段是由Field-collections模块实现的)?


您能告诉我们Drupal和CCK的哪个版本?还有CCK contrib模块吗?
Patrick

Drupal的版本为7
EK的Kosmos

并且您不能在“内容类型管理字段”部分下对其进行修改?您应该可以随时对其进行修改。它可能会给您一个警告,但仍然应该允许它。这可能是字段收集模块中的错误/限制。
Patrick

您是否尝试过使用字段组?现在,您可以执行以前无法执行的操作,例如组复制。
Patrick

我无法在“内容类型管理字段”部分下对其进行修改!这就是重点。Drupal不要让我这样做。
Ek Kosmos

Answers:


89

Dylan Tack解决方案是最简单的解决方案,但是我个人很喜欢探索Drupal数据库的内部区域,以了解如何在此进行管理。

因此,假设您有一个文本字段,其计算机名称是由10个字符组成的field_text,那么您希望增加到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: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 2012年

4
谢谢你 我希望我有一个以上的赞成票。
BC01 2012年

1
这篇文章使用Drupal的Schema API来实现相同的方法:up2technology.com/blog/converting-drupal-fields
Juampy NR

2
如果您不介意将序列化数据发送到Internet,我会发现此工具非常适合编辑:pines.sourceforge.net/phpserialeditor.php
Pete

如果收到有关“ CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL”的错误,则可以使用PhpMyAdmin。
tog22 2014年

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));
}

最喜欢此修复程序,因为它不依赖于手动数据库黑客操作……通过hook_update_N具有可复制的解决方案至关重要!
areynolds 2015年

9

这似乎是当前文本模块的限制。 text_field_settings_form()具有以下注释:“ @todo:如果$ has_data,则添加仅允许max_length增加的验证处理程序。”

作为临时的解决方法,您可以'#disabled' => $has_data在第77行附近的modules / field / modules / text / text.module中注释掉。

我找不到针对此特定案例的现有问题,但您可能会在#372330上提及它。


2
感谢您的回答。我已经注释了这一行,现在我可以修改字段的值,但是Attempt to update field Serial No failed: field_sql_storage cannot change the schema for an existing field with data..
求和

关于提交drupal问题,请继续进行。
Ek Kosmos

1
我无法使它正常工作。在注释该行之后,我仍然收到一个ALTER TABLE失败的MYSQL错误。
jchwebdev 2014年

如果得到一个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文本模块代码中的待办事项表明这是有意的,但从未实现。

需要发生的三件事:

  1. 更改field_data_ {fieldname}表中value列的VARCHAR长度
  2. 更改field_revision_ {fieldname}表中value列的VARCHAR长度
  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。配置类型为“字段存储”,然后选择有问题的字段。复制配置。
  3. 导航至/admin/config/development/configuration/single/import。。配置类型为“字段存储”。粘贴配置。更改长度。
  4. 提交表格。

注意(您可能已经知道),如果缩短长度,那么现有数据将被截断。


这就像一个魅力。从Drupal 8.5.3开始,受保护的函数updateDedicatedTableSchema中的行是1505-1507,受保护的函数updateSharedTableSchema中的行是1596-1598。完成后一定要改回来!谢谢。
HongPong

我首先尝试了这种方法。我正在尝试修改段落字段。它可以工作,但是无论如何都必须更改相应的表。
Yaazkal

@Yaazkal Hmmm,那不是我的经验。您是要延长还是缩短该领域?
大林

@Dalin加长,从255延长到510。使用D 8.5.5和第1.3段
Yaazkal

1

在Drupal 7中,我对phpmyadmin中的2个表进行了修改,并刷新了缓存。

  1. “ field_data_field_lorem”:将“ field_lorem_value”更改为“ longtext”
  2. “ field_config”:将“类型”更改为“ text_long”

您是否将此补丁作为D7的补丁提交了?如果这确实是问题,那么您应该向他们发行补丁以解决核心代码中的问题。
Patrick

我已经将字段大小值从phpmyadmin(从VARCHAR类型的10更改为25),并刷新了缓存,但是无法正常工作。在数据库标记为VARCHAR(25)的数据库中,但在Drupal中,该字段的大小与以前的最大大小相同。10。也许存在一些隐藏字段设置?
Ek Kosmos
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.