Wie ändere ich einen Feldtyp von Integer in Decimal?

7

Ich habe einen Inhaltstyp mit einem ganzzahligen Inhaltsfeld. Das Feld muss Float-Daten enthalten. Was ist der einfachste Weg, um den Feldtyp von Ganzzahl auf Dezimalzahl zu ändern? (Es gibt Tausende von vorhandenen Knoten, die ich konvertieren muss).


Ich habe in diesem Kommentar und diesem Kommentar eine Lösung gefunden . Ist es das beste

Druvision
quelle
Nein. Da es sich um Drupal 6 und CCK handelt, handelt es sich bei dieser Frage um Drupal 7. Die Felder in D7 sind CCK in D6 sehr ähnlich, aber nicht identisch. Der allgemeine Ansatz mag in Ordnung sein, aber Sie müssen Anpassungen vornehmen, damit er auf D7 funktioniert.
Eelke Blok

Antworten:

8

Nur um alle vorherigen Vorschläge zu einem praktischen Teil zusammenzuführen:

// Change this to your field name, obvs.
$field = 'field_myfieldname';

// Update the storage tables
$tables = array('field_data', 'field_revision');
foreach ($tables as $table) {
  $tablename = $table .'_'. $field;
  $fieldname = $field .'_value';
  db_change_field($tablename, $fieldname, $fieldname, array(
    'type' => 'numeric',
    'precision' => 10,
    'scale' => 2,
    'not null' => FALSE,
  ));
}

// Fetch the current field configuration
$field_config = db_query("SELECT data FROM {field_config} WHERE field_name = :field_name", array(
    ':field_name' => $field,
  ))
  ->fetchObject();
$data = unserialize($field_config->data);

// Update the settings entry
$data['settings'] = array(
  'precision' => 10,
  'scale' => 2,
  'decimal_separator' => '.',
);

// Store the new field config, update the field type at the same time
db_update('field_config')
  ->fields(array(
    'data' => serialize($data),
    'type' => 'number_decimal',
  ))
  ->condition('field_name', $field)
  ->execute();    

// If you are confident about what bundles have instances of this field you can
// go straight to the db_query with a hardcoded entity_type / bundle.
$instances = field_info_field_map();
foreach ($instances[$field]['bundles'] as $entity_type => $bundles) {
  foreach ($bundles as $bundle) {

    // Fetch the field instance data
    $field_config_instance = db_query("SELECT data FROM {field_config_instance}
                                       WHERE field_name = :field_name
                                       AND entity_type = :entity_type
                                       AND bundle = :bundle", array(
        ':field_name' => $field,
        ':entity_type' => $entity_type,
        ':bundle' => $bundle,
      ))
      ->fetchObject();
    $data = unserialize($field_config_instance->data);

    // Update it with the new display type
    $data['display']['default']['type'] = 'number_decimal';

    // Store it back to the database
    db_update('field_config_instance')
      ->fields(array('data' => serialize($data)))
      ->condition('field_name', $field)
      ->condition('entity_type', $entity_type)
      ->condition('bundle', $bundle)
      ->execute();

  }
}
KingAndy
quelle
Noch eine Ergänzung; Wenn Sie eine nicht standardmäßige Konfiguration mit verschiedenen Anzeigemodi haben, kann die mit "Mit dem neuen Anzeigetyp aktualisieren" gekennzeichnete Zeile zu Chaos führen. Stattdessen sollten Sie alle Anzeigen durchlaufen, zuerst prüfen, ob das Feld in dieser Anzeige nicht ausgeblendet ist, und es aktualisieren, wenn dies nicht der Fall ist. Bearbeiten: Anscheinend kann ich keinen Code in einem Kommentar posten.
Eelke Blok
1
Hervorragende Lösung. Ich habe es in eine Funktion kopiert, auf die hook_update_n zugreifen kann, und bin auf dem Weg zu den Rennen! Hinweis: Ansichten, Bedienfelder usw., in denen das Feld angezeigt wird, müssen ebenfalls aktualisiert werden. Die Bereitstellung in einem hook_update_n verursacht wahrscheinlich einen Schluckauf und erfordert ein kleines Mischen zwischen Feldwechsel und Zurücksetzen exportierter Features, wenn dies Ihre Tasche ist.
Texas-Bronius
5

Ein besserer Ansatz könnte darin bestehen, die integrierte Funktion von Drupal zu verwenden, um den Feldtyp db_change_field () zu ändern .

db_change_field('field_data_field_number', 'field_number_value', 'field_number_value', array(
  'type' => 'numeric',
  'precision' => 10,
  'scale' => 2,
  'not null' => FALSE,
));
heddn
quelle
Es ist wichtig zu beachten, dass dies keine vollständige Lösung ist, sondern nur eine mögliche Verbesserung gegenüber anderen gegebenen Lösungen. Dies ändert nur den Typ der Datenbankspalte (Feld), nicht die gesamte Drupal-Feldkonvertierung. Grundsätzlich ersetzt es die an anderer Stelle angegebene rohe ALTER-Abfrage.
Eelke Blok
4

Ich habe gerade einen Code geschrieben, der dies für Sie in meinem Hilfsmodul erledigen soll : http://cgit.drupalcode.org/helper/tree/lib/FieldChangeHelper.php?h=7.x-1.x

FieldChangeHelper::changeType('my_int_field_name', 'number_decimal');

Es sollte für die meisten einfachen Fälle und Felder gut funktionieren, sollte aber gründlich getestet werden. Derzeit werden auch keine Feldformatierer aktualisiert. Sie sollten daher die Anzeigekonfiguration für das Feld überprüfen, nachdem Sie dies ausgeführt haben.

Dave Reid
quelle
Das sieht sehr schön aus! Könnten Sie bitte einige
Hinweise
Würde so etwas zum Konvertieren eines Textes in einen Link-Typ funktionieren?
Sonic Thoughts
Dies funktioniert auch mit der neuesten Drupal-Version (derzeit 7.34) recht gut.
Todinov
Dadurch können Präzision und Skalierung nicht eingestellt werden. Standardmäßig ist die Genauigkeit auf 10 und die Skalierung auf 2 festgelegt. Wenn Sie andere Werte festlegen müssen, lesen Sie die Antwort von KingAndy.
Camilo
4

Das obige Modul von Dave Reids drupal.org/project/helper ist eine gute einfache Lösung.

Ich kann oben keinen Kommentar hinzufügen, also schreibe hier Schritte.

1) Laden Sie das Hilfsmodul herunter und aktivieren Sie es

2) Erstellen Sie eine neue Datei: changeIntField.php

<?php
FieldChangeHelper::changeType('my_int_field_name', 'number_decimal');
?>

3) Speichern Sie die Datei im Stammordner, in dem Drupal installiert ist

4) drush scr changeIntField.php

5) Löschen Sie die Datei changeIntFiled.php, da Sie sie nicht mehr benötigen.

6) Bearbeiten Sie das Anzeigeformat für den Knoten / die Entität, in dem das Feld verwendet wird.

7) Ansichten bearbeiten - wo das Feld verwendet wird und auch hier die Einstellungen für das Anzeigeformat korrigieren.

Alauddin
quelle
Das hat super geklappt! Wenn Sie das Devel-Modul installiert haben, können Sie diesen Code auch direkt auf der Seite Excute PHP Code ausführen.
ovi
PS Sie haben einen kleinen Tippfehler in Ihrem Drush-Befehl. es sollte seindrush scr
ovi
Greifen Sie hier auf die Entwicklung des PHP-Ausführungsabschnitts zu: / devel / php
Sam Thompson
Warum nicht einfach drush php-eval "FieldChangeHelper::changeType('my_int_field_name', 'number_decimal');"?
Milkovsky
2

Das Ändern des Typs eines Drupal 7-Inhaltsfelds von einer Ganzzahl in eine Dezimalzahl ist recht einfach. Es ist nicht erforderlich, ein neues Feld zu erstellen und dann die Definitionen zu kopieren. Ich habe die folgenden drei Schritte ausgeführt:

  1. Suchen Sie mithilfe von MySQL den Namen der Feldtabelle und den Namen des Felds in der Tabelle, in der der Feldwert gespeichert ist.

  2. Verwenden Sie die MySQL-Änderungsanweisung, um den Datentyp des Felds zu ändern:
    ALTER TABLE field_data_field_myfield MODIFY field_myfield_value decimal(10,2) ;

  3. Ändern Sie die Felddefinitionen in Drupal:
    UPDATE field_config SET type = 'number_decimal' WHERE field_name = 'field_myfield';

Die Schritte 1 bis 3 sind ausreichend. In bestimmten Fällen kann es jedoch hilfreich sein, die Eigenschaften einer Ganzzahl und eines Dezimalfelds in der Tabelle field_config zu vergleichen, um festzustellen, ob noch etwas geändert werden muss : SELECT id, field_name, type, CONVERT(data USING utf8) FROM field_config WHERE type like 'number_%'.

Druvision
quelle
2

Beachten Sie, dass es für jedes Feld eine andere Tabelle gibt, die als field_revision_field_ {field_name} bezeichnet wird, und dass sich dieser MySQL-Spaltentyp in dieser Tabelle ebenfalls ändern sollte

Auch das Dezimalfeld hat verschiedene Einstellungen, die festgelegt werden sollten. Verwenden Sie das folgende Skript, um die Feldeinstellungen zu unserialisieren. Ändern Sie sie und serialisieren Sie sie erneut. Es gibt zwei Tabellen field_config und field_config_instance. Das Folgende ist für field_config

$s = unserialize('field_config table serialize string');

$s['settings'] = array (
    'precision' => '20',
    'scale' => '0',
    'decimal_separator' => '.',
);

print serialize($s);

Hier ist für die Feldkonfigurationsinstanz:

$s = unserialize('field_config_instance table serialize string');

$s['display']['default']['type'] = 'number_decimal';

print serialize($s);

HINWEIS: Felder können mehr als eine Instanz enthalten, und der nächste Code sollte für alle Instanzen verwendet werden.

Leeren Sie nun den Cache von Drupal und gehen Sie zu den Feldeinstellungen, bearbeiten Sie das Feld und speichern Sie es. Wenn Sie keine Fehlermeldung erhalten, können Sie wahrscheinlich loslegen :)

Sina Salek
quelle
1

Ich musste ein Feld namens "field_margin_percentage" in eine Dezimalzahl ändern

Schritt 1 - Die Datenbankfelder wurden aktualisiert

db_change_field('field_data_field_margin_percentage', 'field_margin_percentage_value', 'field_margin_percentage_value', array(
  'type' => 'numeric',
  'precision' => 10,
  'scale' => 2,
  'not null' => FALSE,
));

Schritt 2 - Aktualisieren Sie die field_config, damit das Feld den richtigen Handler kennt

db_query("UPDATE field_config SET type = 'number_decimal' WHERE field_name = 'field_margin_percentage'");

Schritt 3 - Rufen Sie die vorhandene Datenspalte aus field_config ab und fügen Sie die Dezimaleinstellungen hinzu

$current_field_config = 'a:7:{s:12:"translatable";s:1:"0";s:12:"entity_types";a:0:{}s:8:"settings";a:0:{}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:34:"field_data_field_margin_percentage";a:1:{s:5:"value";s:29:"field_margin_percentage_value";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:38:"field_revision_field_margin_percentage";a:1:{s:5:"value";s:29:"field_margin_percentage_value";}}}}}s:12:"foreign keys";a:0:{}s:7:"indexes";a:0:{}s:2:"id";s:3:"161";}';

$s = unserialize($current_field_config);

$s['settings'] = array (
    'precision' => '10',
    'scale' => '2',
    'decimal_separator' => '.',
);

print serialize($s); // This will give you the new value for the data column (see below)

Schritt 4 - Rufen Sie die vorhandene Datenspalte aus field_config_instance ab und fügen Sie die Dezimaleinstellungen hinzu

$s = unserialize('a:7:{s:5:"label";s:17:"Margin Percentage";s:6:"widget";a:5:{s:6:"weight";s:2:"13";s:4:"type";s:6:"number";s:6:"module";s:6:"number";s:6:"active";i:0;s:8:"settings";a:0:{}}s:8:"settings";a:7:{s:3:"min";s:1:"0";s:3:"max";s:3:"100";s:6:"prefix";s:0:"";s:6:"suffix";s:0:"";s:26:"commerce_user_profile_pane";i:0;s:35:"commerce_user_profile_pane_required";i:0;s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:14:"number_integer";s:6:"weight";s:2:"12";s:8:"settings";a:4:{s:18:"thousand_separator";s:1:" ";s:17:"decimal_separator";s:1:".";s:5:"scale";i:0;s:13:"prefix_suffix";b:1;}s:6:"module";s:6:"number";}}s:8:"required";i:0;s:11:"description";s:115:"The Paddy\'s Seals % of this sale. You can enter this OR the Margin Value. The other one will be calculated for you.";s:13:"default_value";a:1:{i:0;a:1:{s:5:"value";s:1:"0";}}}');

$s['display']['default']['type'] = 'number_decimal';

print serialize($s);

Schritt 5 - Verwenden Sie die oben genannten serialisierten Zeichenfolgen, um Ihre 'Datenspalten' in field_config und field_config_instance zu aktualisieren

db_query('update field_config set data=\'a:7:{s:12:"translatable";s:1:"0";s:12:"entity_types";a:0:{}s:8:"settings";a:3:{s:9:"precision";s:2:"10";s:5:"scale";s:1:"2";s:17:"decimal_separator";s:1:".";}s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:34:"field_data_field_margin_percentage";a:1:{s:5:"value";s:29:"field_margin_percentage_value";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:38:"field_revision_field_margin_percentage";a:1:{s:5:"value";s:29:"field_margin_percentage_value";}}}}}s:12:"foreign keys";a:0:{}s:7:"indexes";a:0:{}s:2:"id";s:3:"161";}\' where field_name=\'field_margin_percentage\'');

db_query('update field_config_instance set data=\'a:7:{s:5:"label";s:17:"Margin Percentage";s:6:"widget";a:5:{s:6:"weight";s:2:"13";s:4:"type";s:6:"number";s:6:"module";s:6:"number";s:6:"active";i:0;s:8:"settings";a:0:{}}s:8:"settings";a:7:{s:3:"min";s:1:"0";s:3:"max";s:3:"100";s:6:"prefix";s:0:"";s:6:"suffix";s:0:"";s:26:"commerce_user_profile_pane";i:0;s:35:"commerce_user_profile_pane_required";i:0;s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:14:"number_decimal";s:6:"weight";s:2:"12";s:8:"settings";a:4:{s:18:"thousand_separator";s:1:" ";s:17:"decimal_separator";s:1:".";s:5:"scale";i:0;s:13:"prefix_suffix";b:1;}s:6:"module";s:6:"number";}}s:8:"required";i:0;s:11:"description";s:115:"The Paddy-s Seals % of this sale. You can enter this OR the Margin Value. The other one will be calculated for you.";s:13:"default_value";a:1:{i:0;a:1:{s:5:"value";s:1:"0";}}}\' where field_name=\'field_margin_percentage\'');
Bryan Gruneberg
quelle
0

So habe ich es gemacht Drupal 7 in einem update_hook_N ().

Der Plan war, ein Feld mit dem Namen "field_ui_current_salary" von DECIMAL (10) in DECIMAL (10,2) zu ändern, wodurch 2 Dezimalstellen für die Werte anstelle von überhaupt keinen Dezimalstellen zulässig sind!

/**
 * Changing Database Currenty Salary field to allow decimals.
 * Replace MYMODULE with your module's name and number N with your next incremented value.
 */
function MYMODULE_update_7001() {
  // field_ui_current_salary scale = 2 in field_config table.
  // Use your 'data' value for $new_data from 'field_config' table for your field and just change where 'scale' is from 0 to 2 (or your desired number of decimals)
  $new_data = 'a:8:{s:12:"entity_types";a:0:{}s:17:"field_permissions";a:1:{s:4:"type";i:0;}s:7:"indexes";a:0:{}s:8:"settings";a:5:{s:3:"max";d:99999999.989999995;s:3:"min";d:-99999999.989999995;s:9:"precision";i:10;s:16:"profile2_private";b:0;s:5:**"scale";i:2;**}s:12:"translatable";i:0;s:7:"storage";a:5:{s:4:"type";s:17:"field_sql_storage";s:8:"settings";a:0:{}s:6:"module";s:17:"field_sql_storage";s:6:"active";s:1:"1";s:7:"details";a:1:{s:3:"sql";a:2:{s:18:"FIELD_LOAD_CURRENT";a:1:{s:34:"field_data_field_ui_current_salary";a:2:{s:6:"amount";s:30:"field_ui_current_salary_amount";s:8:"currency";s:32:"field_ui_current_salary_currency";}}s:19:"FIELD_LOAD_REVISION";a:1:{s:38:"field_revision_field_ui_current_salary";a:2:{s:6:"amount";s:30:"field_ui_current_salary_amount";s:8:"currency";s:32:"field_ui_current_salary_currency";}}}}}s:12:"foreign keys";a:0:{}s:2:"id";s:3:"372";}';
  db_query('UPDATE {field_config} SET data = :new_data WHERE field_name = :salary;', array(':new_data' => $new_data, ':salary' => 'field_ui_current_salary'));

  // field_data_field_ui_current_salary and its revision copy -> DECIMAL(10,2)
  db_query("ALTER TABLE {field_data_field_ui_current_salary} MODIFY field_ui_current_salary_amount DECIMAL(10,2);");
  db_query("ALTER TABLE {field_revision_field_ui_current_salary} MODIFY field_ui_current_salary_amount DECIMAL(10,2);");

  cache_clear_all();
}
Ales Rebec
quelle
0

Die ursprüngliche Frage betraf Drupal 7, aber ich vermute, viele Leute fragen sich, wie dies in Drupal 8 zu tun ist. Leider gibt es derzeit keine gute Methode dafür. Die am wenigsten schlechte Option besteht darin, das Feld (und alle darin enthaltenen Daten) einfach zu löschen und Drupal es von Grund auf neu erstellen zu lassen.

Ich versuche eine bessere Lösung zu finden und werde hier posten, ob und wann sie verfügbar ist: https://www.drupal.org/node/2843108

Dane Powell
quelle