web-dev-qa-db-fra.com

Comment changer un type de champ de Entier en Décimal?

J'ai un type de contenu avec un champ de contenu entier. Le champ doit contenir des données flottantes. Quelle est la manière la plus simple de changer le type de champ de entier en décimal? (Il y a des milliers de nœuds existants que je devrai convertir).


J'ai trouvé une solution dans ce commentaire et ce commentaire . C'est le meilleur?

7
Druvision

Juste pour fusionner toutes les suggestions précédentes en un seul morceau pratique:

// 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();

  }
}
8
KingAndy

Une meilleure approche pourrait être d'utiliser la capacité intégrée de Drupal pour modifier le type de champ, db_change_field () .

db_change_field('field_data_field_number', 'field_number_value', 'field_number_value', array(
  'type' => 'numeric',
  'precision' => 10,
  'scale' => 2,
  'not null' => FALSE,
));
5
heddn

Le module Dave Reids drupal.org/project/helper ci-dessus est une bonne solution simple.

Impossible d'ajouter le commentaire ci-dessus, alors publiez les étapes ici.

1) Téléchargez et activez le module d'assistance

2) Créez un nouveau fichier: changeIntField.php

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

3) Enregistrez le fichier dans le dossier racine où drupal est installé

4) Drush Scr ChangeIntField.php

5) Supprimez le fichier changeIntFiled.php car vous n'en avez plus besoin.

6) Modifier le format d'affichage du nœud/entité où le champ est utilisé.

7) Modifier les vues - où le champ est utilisé et fixer les paramètres de format d'affichage ici également.

4
Alauddin

Je viens d'écrire du code qui devrait gérer cela pour vous dans mon module d'assistance : http://cgit.drupalcode.org/helper/tree/lib/FieldChangeHelper.php?h=7 .x-1.x

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

Il devrait fonctionner correctement pour la plupart des cas et des champs simples, mais devrait être testé de manière approfondie. De plus, il ne met actuellement à jour aucun formateur de champ, vous voudrez donc revoir la configuration d'affichage du champ après l'avoir exécuté.

4
Dave Reid

Changer le type d'un champ de contenu Drupal 7 d'entier en décimal est assez simple. Il n'est pas nécessaire de créer un nouveau champ puis de copier les définitions. J'ai suivi les trois étapes suivantes:

  1. Trouvez le nom de la table du champ et le nom du champ dans cette table où la valeur du champ est stockée, en utilisant MySQL.

  2. Utilisez l'alter statment MySQL pour modifier le type de données du champ:
    ALTER TABLE field_data_field_myfield MODIFY field_myfield_value decimal(10,2) ;

  3. Modifiez les définitions de champ dans Drupal:
    UPDATE field_config SET type = 'number_decimal' WHERE field_name = 'field_myfield';

Les étapes 1 à 3 suffisent. Bien que, dans certains cas, il puisse être avantageux de comparer les propriétés d'un champ entier et d'un champ décimal sur la table field_config pour voir s'il y a autre chose qui doit être changé: SELECT id, field_name, type, CONVERT(data USING utf8) FROM field_config WHERE type like 'number_%'.

2
Druvision

Notez qu'il existe une autre table pour chaque champ qui est appelée field_revision_field_ {field_name} et ce type de colonne mysql de table doit également changer

Le champ décimal a également différents paramètres qui doivent être définis, utilisez le script suivant pour annuler la sérialisation des paramètres de champ, puis sérialisez-le à nouveau. Il existe deux tables field_config et field_config_instance. ce qui suit est pour field_config

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

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

print serialize($s);

voici pour l'instance de configuration de champ:

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

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

print serialize($s);

REMARQUE: les champs peuvent contenir plusieurs instances et le code suivant doit être utilisé pour toutes les instances.

Maintenant, videz le cache de Drupal et accédez aux paramètres du champ, modifiez le champ et enregistrez-le. Si vous ne recevez aucune erreur, vous êtes probablement prêt à partir :)

2
Sina Salek

J'ai dû changer un champ appelé "field_margin_percentage" en décimal

Étape 1 - Mise à jour des champs de la base de données

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

Étape 2 - Mettez à jour le champ_config afin que le champ connaisse le bon gestionnaire

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

Étape 3 - Obtenez la colonne "données" existante de field_config et ajoutez les paramètres décimaux

$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)

Étape 4 - Obtenez la colonne "données" existante de field_config_instance et ajoutez les paramètres décimaux

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

Étape 5 - Utilisez les chaînes sérialisées ci-dessus pour mettre à jour vos colonnes "données" dans field_config et field_config_instance

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\'');
1
Bryan Gruneberg

Voici comment je l'ai fait Drupal 7 dans un update_hook_N ().

Le plan était de changer un champ appelé "field_ui_current_salary" de DECIMAL (10) à DECIMAL (10,2), ce qui permettrait 2 décimales pour les valeurs au lieu de pas de décimales du tout!

/**
 * 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();
}
0
Ales Rebec

La question initiale portait sur Drupal 7, mais je soupçonne que beaucoup de gens se demandent comment faire cela dans Drupal 8. Malheureusement, il n'y a pas de bonne méthode pour le moment. La moins mauvaise option est de simplement supprimer le champ (et toutes les données qu'il contient) et de laisser Drupal le recréer à partir de zéro.

J'essaie de trouver une meilleure solution et je publierai ici si et quand elle sera disponible: https://www.drupal.org/node/2843108

0
Dane Powell