web-dev-qa-db-ja.com

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

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

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

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

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

47
Ek Kosmos

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

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

  • データは、field_data_field_textとfield_revision_field_textの2つのテーブルに格納されます。
  • 定義は、ストレージデータのfield_configに格納され、このフィールドの各インスタンス(labelなど)の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. definition列を変更します。これは、[〜#〜] 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 serialized 配列です。興味深い部分は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を取得するときにも、あなたの人生を救うことができます。

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

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

一時的な回避策として、'#disabled' => $has_data 77行目前後のmodules/field/modules/text/text.module.

この特定のケースで既存の問題を見つけることはできませんでしたが、 #3723 で言及するかもしれません。

9
Dylan Tack

Drupal 7

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

データが失われる可能性があるため、最大長を短くすると無効になることは理解できますが、任意のフィールドの最大長を大きくすることは可能です。 Drupal 7テキストモジュールコードの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
    );
  }
}
7
kenorb

これを試してください...これにより、フィールドのデータ型がTEXTからLONG_TEXTに更新され、max_length 4000からテキストの最大長まで...これがお役に立てば幸いです。

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

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

3
Dalin

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

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