フィールド設定の長さを変更するには?


46

私は一度ウェブサイトにフィールドの長さ制限を設定しました。そして今、クライアントはそのフィールドにより多くの文字を入れたいと思っています。

次のエラーメッセージが表示されるため、Drupalから最大サイズを変更できません。

データベースにこのフィールドのデータがあります。フィールド設定は変更できなくなりました。

ただし、解決策が必要です。データベースで変更しますか(フィールドは、Field-collectionsモジュールによって実装されたものです)?


DrupalとCCKのバージョンを教えてください。CCK contribモジュールもありますか?
パトリック

Drupalバージョンは7です。
Ekコスモス

また、コンテンツタイプの管理フィールドセクションでは変更できませんか?いつでも変更できるはずです。警告が表示される場合がありますが、それでも許可する必要があります。これは、フィールドコレクションモジュールのバグ/制限の可能性があります。
パトリック

フィールドグループを使用してみましたか?これで、以前はできなかったグループの複製などを行うことができます。
パトリック

コンテンツタイプのフィールド管理セクションでは変更できません!これがポイントです。Drupalは私にそれをさせません。
Ekコスモス

回答:


89

Dylan Tackソリューションは最も簡単ですが、個人的には、Drupalのデータベースの内部を探索して、そこでの管理方法を確認するのを楽しんでいます。

そのため、マシン名が10文字のfield_textであるテキストフィールドがあると仮定して、25に拡大します。

  • データは、field_data_field_textとfield_revision_field_textの2つのテーブルに保存されます
  • 定義は、ストレージデータのfield_config、およびこのフィールドの各インスタンス(ラベルなど)のfield_config_instanceに格納されます。

それでは、少し心臓手術をしましょう。

  1. データテーブルの列定義を変更します。

    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. 定義列を変更します。これはBLOBに格納されているため非常に注意が必要ですが、これを行うことを妨げるものではありません。

    • このBLOBの本質を分析します。

    SELECT CAST(`data` AS CHAR(10000) CHARACTER SET utf8) 
    FROM `field_config` WHERE field_name = 'field_text';
    • これにより、次のようなものが得られます。

    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...
    • これはPHP シリアル化配列です。興味深いのはs:10:"max_length";s:2:"10";、この配列には、max_length名前が10文字の文字列(つまり「s」)という名前のプロパティがあり、値は10(2文字の文字列)であるということです。とても簡単ですね。

    • 値を変更するのは、s:2:"10"部品をに置き換えるのと同じくらい簡単s:2:"25"です。注意:新しい値が長い場合は、「s」部分を調整する必要があります。たとえば、100を入力するとs:3:"100"100の長さは3になります。

    • この新しい値をDBに戻しましょう。文字列全体を保持することを忘れないでください。

    UPDATE `field_config` 
    SET data = 'a:7:{...a:2:{s:10:"max_length";s:2:"25";...}'
    WHERE `field_name` = 'field_text'
    • キャッシュをフラッシュします。
  3. ???

  4. 利益!

ちなみに、PhpMyAdminにはBLOB列の直接変更を許可する設定がありますが、なぜ簡単な方法がありますか?

PS:これは、コードにエラーがあるために、ビューにPHPコードを入れてWSODを取得するときの命も救うことができます。


その最初のSQLステートメントはそうでALTER TABLEはありませんSELECT TABLE。また、あなたはクリーナーのようなことを行うことができますALTER TABLE field_data_field_text MODIFY field_text_value...(あなたが変更したくない場合にMODIFYは、CHANGEのようなものです名前をそして、あなたはしないでください。)
artfulrobot

4
これをありがとう。複数の賛成票があればいいのに。
-BC01

1
この投稿では、DrupalのスキーマAPIを使用して同じアプローチを実現しています。up2technology.com
blog

2
あなたがのインターネットに自分のシリアル化されたデータを送信して気にしない場合は、私が編集するための偉大な、このツールを見つけました:pines.sourceforge.net/phpserialeditor.phpを
ピート・

「CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL」に関するエラーが発生した場合は、PhpMyAdminを使用できます。
tog22

19
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));
}

手動のDBハッカーに依存しないため、この修正が最も好きです... hook_update_Nを介した複製可能なソリューションが不可欠です!
アリーノルズ

9

これは、現在のテキストモジュールの制限のようです。 text_field_settings_form()には次のコメントがあります: " @todo:$ has_dataの場合、max_lengthの増加のみを許可する検証ハンドラーを追加します。"

一時的な回避策として、'#disabled' => $has_datamodules / field / modules / text / text.moduleの77行目でコメントアウトできます。

この特定のケースに関する既存の問題は見つかりませんでしたが、#372330で言及するかもしれません。


2
ご回答有難うございます。しかし、私はsumbit後に次のエラーを取得する、私は行をコメントしているし、今私は、値のフォームにフィールドを変更することができますAttempt to update field Serial No failed: field_sql_storage cannot change the schema for an existing field with data..
エックコスモス

drupal問題のコミットについては、先に進んでください。
エックコスモス

1
これを機能させることができませんでした。その行にコメントを付けた後、ALTER TABLEが失敗したというMYSQLエラーがまだありました。
jchwebdev 14

を取得する場合は、FieldUpdateForbiddenException: cannot change the schema for an existing field with dataL282でコメントアウトする必要もありますmodules/field/modules/field_sql_storage/field_sql_storage.module
ダイエウ

@dieuweのコメントは間違っています。そのファイルは、最近のバージョンのD8には存在しません(存在した場合)。core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php「SQLストレージは既存のフィールドのスキーマを変更できません」というテキストで例外をスローする2行をコメント化する必要があります。1312行目と1403行目について
Dalin

6

Drupal 7

Drupal 7でテキストフィールドを作成する場合、データの最大長を選択する必要があります。このフィールドのデータを作成するとすぐに、Drupalフィールドの設定で最大長が不変になります。

データの損失につながる可能性があるため、これが最大長を減らすために無効にされることは理解できますが、任意のフィールドの最大長を増やすことは可能です。Drupal 7 Textモジュールコードのtodoは、これが意図されていたが、決して達成されなかったことを示しています。

発生する必要がある3つのこと:

  1. field_data_ {fieldname}テーブルの値列のVARCHAR長を変更します
  2. field_revision_ {fieldname}テーブルの値列のVARCHAR長を変更します
  3. 新しい最大長の設定を反映するようにフィールドの構成を更新します。次の機能は、これらの3つの手順をすべて実行し、フィールドの名前と新しい最大長を含む2つの簡単なパラメーターを取ります。
/**
 * 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();
}

カスタムインストールファイルでこの関数を使用できるようになったら、この新しい関数を使用して必要な変更を加える新しいデータベース更新関数を作成できます。

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

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


Drupal 8

@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
    );
  }
}

1
このdrupal 8メソッドをプロジェクトで使用し、問題が発生したdrush updb --entity-updatesため、フィールドを実行すると、この関数を実行したときに更新が必要とマークされます。その後、mysqlでフィールドスキーマを再度更新しようとします。この場合、フィールドデータが既に存在するため、これは失敗します。これは、他の更新タスクの実行を妨げていました。
leon.nk

簡単に言えば、新しいフィールドを作成してデータを移行する方がおそらく安全です。
leon.nk

3

これを試してください...これにより、フィールドのデータ型がTEXTからLONG_TEXTに更新され、max_length4000から最大長テキスト長に更新されます...これが役立つことを願っています。

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

D8

  1. core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchem‌​a.php「SQLストレージは既存のフィールドのスキーマを変更できません」というテキストで例外をスローする2行をコメント化します。行1312および1403について。
  2. ブラウザで、に移動し/admin/config/development/configuration/single/exportます。構成タイプは「フィールドストレージ」であり、問​​題のフィールドを選択します。構成をコピーします。
  3. に移動し/admin/config/development/configuration/single/importます。。構成タイプは「フィールドストレージ」です。構成を貼り付けます。長さを変更します。
  4. フォームを送信します。

注(おそらく既にご存知のとおり)、長さを短くすると、既存のデータは切り捨てられます。


これは魅力的でした。Drupal 8.5.3の時点で、行は保護機能updateDedicatedTableSchemaで1505-1507、保護機能updateSharedTableSchemaで1596-1598です。完了したら元に戻してください!ありがとうございました。
ホンポン

私は最初にこのアプローチを試しました。段落フィールドを変更しようとしています。動作しますが、とにかく対応するテーブルを変更することが必須です。
ヤアズカル

@Yaazkalうーん、それは私の経験ではなかった。フィールドを延長または短縮しようとしていますか?
ダリン

@Dalinは、255から510に長くなります。D8.5.5および段落1.3を使用
Yaazkal

1

Drupal 7では、phpmyadminの2つのテーブルに変更を加え、キャッシュを更新しました。

  1. 「field_data_field_lorem」:「field_lorem_value」を「longtext」に変更
  2. 「field_config」:「type」を「text_long」に変更

これをパッチとしてD7に提出しましたか?これが本当に問題である場合は、コアコードでこの問題を解決するために、実際にパッチを発行する必要があります。
パトリック

フィールドサイズの値をphpmyadmin(VARCHAR型の10から25)に変更し、キャッシュを更新しましたが、動作していません。データベースではVARCHAR(25)が維持されていますが、Drupalでは、フィールドの最大サイズは10以前と同じです。
エックコスモス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.