フィールドタイプを整数から10進数に変更する方法は?


7

整数のコンテンツフィールドを持つコンテンツタイプがあります。フィールドには浮動小数点データを含める必要があります。フィールドタイプを整数から10進数に変更する最も簡単な方法は何ですか?(変換する必要がある既存のノードは何千もあります)。


このコメントこのコメントで解決策を見つけました。最高ですか?


いいえ。Drupal6とCCKを扱います。この質問はDrupal 7についてです。D7のフィールドはD6のCCKとよく似ていますが、同じではありません。一般的なアプローチは問題ないかもしれませんが、D7で機能させるには微調整が必​​要です。
Eelke Blok、2015

回答:


8

以前のすべての提案を1つの便利なチャンクにマージするだけです。

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

  }
}

もう1つ追加。異なる表示モードの非標準構成を使用している場合、「新しい表示タイプで更新する」とマークされた行が大混乱を引き起こす可能性があります。代わりに、すべての表示をループして、まずその表示でフィールドが非表示になっていないかどうかを確認し、非表示になっていない場合は更新する必要があります。編集:どうやら、コメントにコードを投稿することはできません。
Eelke Blok、2015

1
優れたソリューション。私はそれをhook_update_nでアクセス可能な関数にコピーし、レースに出かけます!注:フィールドを表示するビュー、パネルなども更新する必要があります。これをhook_update_nにデプロイすると問題が発生する可能性が高く、フィールドの変更とエクスポートされた機能の復帰の間に少し手を加える必要があります。
texas-bronius

5

Drupalの組み込み機能を使用してフィールドタイプ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,
));

これは完全なソリューションではなく、他のソリューションよりも改善される可能性があることに注意してください。これはデータベースの列(フィールド)のタイプを変更するだけで、Drupalフィールド全体の変換は行いません。基本的には、他の場所で指定された生のALTERクエリを置き換えます。
Eelke Blok、2015

4

ヘルパーモジュールでこれを処理するためのコードをいくつか書いたところです。http//cgit.drupalcode.org/helper/tree/lib/FieldChangeHelper.php?h = 7.x-1.x

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

ほとんどの単純なケースとフィールドでは問題なく機能しますが、徹底的にテストする必要があります。現在、フィールドフォーマッタも更新されていないため、これを実行した後、フィールドの表示設定を確認する必要があります。


これはとても素敵に見えます!初心者向けのモジュールの使用方法について、ここにいくつかの指針を示してください:)
petergus 14年

このようなものはテキストをリンクタイプに変換するのに役立ちますか?
Sonicthoughts、2014年

これは、最新のdrupalバージョン(現在は7.34)でも十分機能します。
todinov 2014

これにより、精度とスケールを設定できません。デフォルトでは、精度を10に設定し、スケールを2に設定します。別の値を設定する必要がある場合は、KingAndyの回答をご覧ください。
Camilo、

4

上記のDave Reids drupal.org/project/helperモジュールは、優れたシンプルなソリューションです。

上記にコメントを追加できないので、ここに手順を投稿してください。

1)ヘルパーモジュールをダウンロードして有効にする

2)新しいファイルを作成します:changeIntField.php

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

3)drupalがインストールされているルートフォルダーにファイルを保存します

4)drush scr changeIntField.php

5)不要になったファイルchangeIntFiled.phpを削除します。

6)フィールドが使用されているノード/エンティティの表示形式を編集します。

7)ビューの編集-フィールドが使用される場所と、ここでも表示形式設定を修正します。


これはうまくいきました!Develモジュールがインストールされている場合は、このコードを[Excute PHP Code]ページから直接実行することもできます。
ovi

PSあなたはあなたのdrushコマンドに小さなタイプミスがあります。それはする必要がありますdrush scr
ovi

ここでphp実行セクションdevelにアクセスします:/ devel / php
Sam Thompson

なぜdrush php-eval "FieldChangeHelper::changeType('my_int_field_name', 'number_decimal');"ですか?
milkovsky 2017年

2

Drupal 7コンテンツフィールドのタイプを整数から10進数に変更するのは非常に簡単です。新しいフィールドを作成してから定義をコピーする必要はありません。私は次の3つのステップを使用しました。

  1. MySQLを使用して、フィールドのテーブルの名前と、フィールドの値が格納されているそのテーブル内のフィールドの名前を見つけます。

  2. MySQL変更ステートメントを使用して、フィールドのデータ型を変更します。
    ALTER TABLE field_data_field_myfield MODIFY field_myfield_value decimal(10,2) ;

  3. Drupalでフィールド定義を変更します。
    UPDATE field_config SET type = 'number_decimal' WHERE field_name = 'field_myfield';

手順1〜3で十分です。ただし、場合によっては、field_configテーブルの整数フィールドと10進数フィールドのプロパティを比較して、変更が必要なものが他にあるかどうかを確認すると便利な場合がありますSELECT id, field_name, type, CONVERT(data USING utf8) FROM field_config WHERE type like 'number_%'


2

各フィールドにはfield_revision_field_ {field_name}と呼ばれる別のテーブルがあり、このテーブルのmysql列タイプも変更されることに注意してください

また、10進数フィールドには異なる設定が必要です。次のスクリプトを使用して、フィールド設定のシリアル化を解除して変更し、再度シリアル化してください。2つのテーブルfield_configとfield_config_instanceがあります。以下はfield_config用です

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

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

print serialize($s);

ここにフィールド設定インスタンスがあります:

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

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

print serialize($s);

注:フィールドには複数のインスタンスが含まれる場合があり、すべてのインスタンスに次のコードを使用する必要があります。

Drupalのキャッシュをクリアし、フィールド設定に進み、フィールドを編集して保存します。エラーが表示されない場合は、おそらく問題ありません:)


1

「field_margin_percentage」というフィールドを10進数に変更する必要がありました

手順1-データベースのフィールドを更新しました

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

ステップ2-フィールドが正しいハンドラーを認識するようにfield_configを更新します

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

手順3-field_configから既存の「データ」列を取得し、10進設定を追加する

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

ステップ4-field_config_instanceから既存の「データ」列を取得し、10進設定を追加する

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

ステップ5-上記のシリアル化された文字列を使用して、field_configおよび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\'');

0

これが私がupdate_hook_N()でDrupal 7を実行した方法です。

計画では、 "field_ui_current_salary"と呼ばれる1つのフィールドをDECIMAL(10)からDECIMAL(10,2)に変更し、小数をまったく使用せずに2つの小数点を許可しました。

/**
 * 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

元の質問はDrupal 7に関するものでしたが、多くの人がDrupal 8でこれを行う方法を疑問に思っていると思います。残念ながら、現時点でこれを行うための適切な方法はありません。最も悪い方法は、フィールド(およびフィールドに含まれるデータ)を単に削除し、Drupalに最初から再作成させることです。

私はより良い解決策を見つけようとしているので、それが利用できる場合はここに投稿します:https : //www.drupal.org/node/2843108

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.