it-swarm.it

Come modificare la lunghezza delle impostazioni del campo?

Ho impostato una volta su un sito Web un limite di lunghezza per un campo. E ora il cliente vuole mettere più caratteri in quel campo.

Non riesco a modificare la dimensione massima da Drupal perché visualizzo il seguente messaggio di errore:

Ci sono dati per questo campo nel database. Le impostazioni del campo non possono più essere modificate.

Tuttavia, ci deve essere una soluzione. Devo cambiarlo nel database (il campo è uno implementato dal modulo Field-collections )?

47
Ek Kosmos

La soluzione di Dylan Tack è la più semplice, ma personalmente mi piace esplorare i reparti interni del database di Drupal per vedere come vengono gestite le cose laggiù.

Quindi, supponendo che tu abbia un campo di testo il cui nome macchina è field_text di 10 caratteri che vuoi aumentare a 25:

  • i dati verranno archiviati in due tabelle: field_data_field_text e field_revision_field_text
  • la definizione viene archiviata in field_config per i dati di archiviazione e field_config_instance per ogni istanza di questo campo (elementi come l'etichetta).

Ora facciamo un piccolo intervento al cuore.

  1. Modifica le definizioni delle colonne delle tabelle di dati:

    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. Cambia la colonna definizione , questa è molto complicata perché è memorizzata in un blob [~ # ~] [~ # ~], ma non è qualcosa che ti impedirà di farlo.

    • Sezionare l'intestino di questa cosa [~ # ~] blob [~ # ~]:
    SELECT CAST(`data` AS CHAR(10000) CHARACTER SET utf8) 
    FROM `field_config` WHERE field_name = 'field_text';
    
    • Questo ti darà qualcosa di simile:
    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...
    
    • Questo è un array PHP serializzato , la parte interessante è s:10:"max_length";s:2:"10";, questo significa che questo array ha una proprietà chiamata max_length (il cui nome è una stringa di 10 caratteri - da qui la "s") il cui valore è 10 (che è una stringa lunga 2 caratteri). È abbastanza facile, no?

    • Cambiare il suo valore è facile come sostituire s:2:"10" parte di s:2:"25". Fai attenzione: se il tuo nuovo valore è più lungo devi adattare la parte "s", ad esempio mettendo 100 sarà s:3:"100" come 100 lunghezza è 3.

    • Rimettiamo questo nuovo valore nel DB, non dimenticare di mantenere l'intera stringa.

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

  4. PROFITTO!

A proposito, PhpMyAdmin ha alcune impostazioni per consentire modifica diretta delle colonne BLOB , ma perché andare nel modo più semplice?

PS: Questo può anche salvarti la vita quando metti un po 'PHP nelle viste e ottieni un WSOD a causa di un errore nel tuo codice.

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

Questo sembra essere un limite del modulo di testo corrente. text_field_settings_form () ha questo commento: " @ todo : Se $ has_data, aggiungi un gestore valido che consenta solo di aumentare max_length . ".

Come soluzione temporanea, puoi commentare '#disabled' => $has_data in modules/field/modules/text/text.module, attorno alla riga 77.

Non sono riuscito a trovare un problema esistente per questo caso specifico, ma potresti menzionarlo su # 3723 .

9
Dylan Tack

Drupal 7

Quando si crea un campo di testo in Drupal 7, è necessario scegliere una lunghezza massima per i dati. Non appena si creano dati per questo campo, la lunghezza massima diventa immutabile in Drupal impostazioni sul campo.

È comprensibile che questo sia disabilitato per ridurre la lunghezza massima perché potrebbe comportare una perdita di dati, tuttavia, dovrebbe essere possibile aumentare la lunghezza massima per qualsiasi campo. Un todo nel Drupal 7 codice del modulo di testo mostra che questo era previsto ma mai realizzato.

Le 3 cose che devono accadere:

  1. Modificare la lunghezza VARCHAR della colonna del valore nella tabella field_data_ {fieldname}
  2. Modificare la lunghezza VARCHAR della colonna del valore nella tabella field_revision_ {fieldname}
  3. Aggiorna la configurazione del campo in modo che rifletta la nuova impostazione della lunghezza massima La seguente funzione esegue tutti e 3 questi passaggi e accetta 2 semplici parametri tra cui il nome del campo e la nuova lunghezza massima.
/**
 * 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();
}

Quando questa funzione è disponibile nel file di installazione personalizzato, è possibile creare una nuova funzione di aggiornamento del database che utilizza questa nuova funzione per apportare le modifiche richieste.

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

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


Drupal 8

Ecco la versione della stessa funzione proposta da @ 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

Prova questo ... questo aggiornerà il tipo di dati del campo da TEXT a LONG_TEXT e aggiornerà il max_length da 4000 a una lunghezza massima del testo ... spero che questo aiuti.

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. Commenta le due righe in core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchem‌​a.php che generano eccezioni con il testo "La memoria SQL non può modificare lo schema per un campo esistente". Circa le linee 1312 e 1403.
  2. Nel tuo browser, vai a /admin/config/development/configuration/single/export. Il tipo di configurazione è "Archiviazione campo" e scegli il campo in questione. Copia la configurazione.
  3. Navigare verso /admin/config/development/configuration/single/import. . Il tipo di configurazione è "Archiviazione su campo". Incolla la configurazione. Cambia la lunghezza.
  4. Invia il modulo.

Nota (come probabilmente già saprai), se accorcia la lunghezza, i dati esistenti verranno troncati.

3
Dalin

In Drupal 7, ho apportato modifiche a 2 tabelle in phpmyadmin e ho aggiornato la cache.

  1. "field_data_field_lorem": modificato "field_lorem_value" in "longtext"
  2. "field_config": modificato "type" in "text_long"
1
Jill