it-swarm-es.com

¿Cómo cambiar la longitud de la configuración de campo?

He establecido una vez en un sitio web un límite de longitud para un campo. Y ahora el cliente quiere poner más personajes en ese campo.

No puedo cambiar el tamaño máximo de Drupal porque recibo el siguiente mensaje de error:

Hay datos para este campo en la base de datos. La configuración del campo ya no se puede cambiar.

Sin embargo, debe haber una solución. ¿Debo cambiarlo en la base de datos (el campo es uno implementado por el módulo Field-collections )?

47
Ek Kosmos

La solución Dylan Tack es la más fácil, pero personalmente disfruto explorando los barrios internos de la base de datos de Drupal para ver cómo se manejan las cosas allí.

Entonces, suponiendo que tiene un campo de texto cuyo nombre de máquina es field_text de 10 caracteres que desea aumentar a 25:

  • los datos se almacenarán en dos tablas: field_data_field_text y field_revision_field_text
  • la definición se almacena en field_config para los datos de almacenamiento y field_config_instance para cada instancia de este campo (cosas como etiqueta).

Ahora hagamos una pequeña cirugía de corazón.

  1. Modifique las definiciones de columnas de las tablas de datos:

    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. Cambie la columna de definición , ¡esta es muy complicada porque está almacenada en un blob [~ # ~] [~ # ~], pero eso no es algo que te detendrá por hacer esto.

    • Diseccionar las entrañas de este [~ # ~] blob [~ # ~] cosa:
    SELECT CAST(`data` AS CHAR(10000) CHARACTER SET utf8) 
    FROM `field_config` WHERE field_name = 'field_text';
    
    • Esto te dará algo como:
    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...
    
    • Esta es una matriz PHP serializada , la parte interesante es s:10:"max_length";s:2:"10";, esto significa que esta matriz tiene una propiedad llamada max_length (cuyo nombre es una cadena de 10 caracteres, de ahí la "s") cuyo valor es 10 (que es una cadena de 2 caracteres de longitud). Es bastante fácil, ¿no es así?

    • Cambiar su valor es tan fácil como reemplazar el s:2:"10" parte por s:2:"25". Tenga cuidado: si su nuevo valor es más largo, debe adaptar la parte "s", por ejemplo, poner 100 será s:3:"100" como 100 longitud es 3.

    • Volvamos a poner este nuevo valor en la base de datos, no olvides mantener toda la cadena.

    UPDATE `field_config` 
    SET data = 'a:7:{...a:2:{s:10:"max_length";s:2:"25";...}'
    WHERE `field_name` = 'field_text'
    
    • Limpia tus cachés.
  3. ???

  4. ¡LUCRO!

Por cierto, PhpMyAdmin tiene alguna configuración para permitir modificación directa de columnas BLOB , pero ¿por qué seguir el camino fácil?

PD: Esto también puede salvarle la vida al poner un código PHP en las vistas y obtener un WSOD debido a un error en su código.

89
tostinni
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));
}
20
Kevin Thompson

Esto parece ser una limitación del módulo de texto actual. text_field_settings_form () tiene este comentario: " @ todo : si $ has_data, agregue un controlador de validación que solo permita que max_length aumente ".

Como solución temporal, puede comentar '#disabled' => $has_data en modules/field/modules/text/text.module, alrededor de la línea 77.

No pude encontrar un problema existente para este caso específico, pero podría mencionarlo en # 3723 .

9
Dylan Tack

Drupal 7

Al crear un campo de texto en Drupal 7, debe elegir una longitud máxima para sus datos. Tan pronto como cree datos para este campo, la longitud máxima se volverá inmutable en Drupal.

Es comprensible que esto se desactive para disminuir la longitud máxima porque podría provocar una pérdida de datos, sin embargo, debería ser posible aumentar la longitud máxima para cualquier campo. Un todo en el Drupal 7 El código del módulo de texto muestra que esto fue intencionado pero nunca logrado.

Las 3 cosas que deben suceder:

  1. Cambie la longitud VARCHAR de la columna de valor en la tabla field_data_ {fieldname}
  2. Cambie la longitud VARCHAR de la columna de valor en la tabla field_revision_ {fieldname}
  3. Actualice la configuración del campo para reflejar la nueva configuración de longitud máxima La siguiente función realiza los 3 pasos y toma 2 parámetros sencillos, incluido el nombre del campo y la nueva longitud máxima.
/**
 * 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();
}

Una vez que esta función esté disponible en su archivo de instalación personalizado, puede crear una nueva función de actualización de la base de datos que utilice esta nueva función para realizar los cambios necesarios.

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

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


Drupal 8

Aquí está la versión de la misma función propuesta por @ 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
    );
  }
}
7
kenorb

Pruebe esto ... esto actualizará el tipo de datos de campo de TEXT a LONG_TEXT y actualizará el max_length de 4000 a la longitud máxima de texto largo ... espero que esto ayude.

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
Harold

D8

  1. Comente las dos líneas en core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchem‌​a.php que arrojan excepciones con el texto "El almacenamiento SQL no puede cambiar el esquema de un campo existente". Sobre las líneas 1312 y 1403.
  2. En su navegador, navegue hasta /admin/config/development/configuration/single/export. El tipo de configuración es "Almacenamiento de campo" y elija el campo en cuestión. Copia la configuración.
  3. Navegar a /admin/config/development/configuration/single/import. . El tipo de configuración es "Almacenamiento de campo". Pega la configuración. Cambia la longitud.
  4. Envíe el formulario.

Nota (como probablemente ya sepa), si acorta la longitud, los datos existentes se truncarán.

3
Dalin

En Drupal 7, realicé modificaciones en 2 tablas en phpmyadmin, y actualicé el caché.

  1. "field_data_field_lorem": cambió "field_lorem_value" a "texto largo"
  2. "field_config": cambió "type" a "text_long"
1
Jill