値のデータがある選択フィールドの許可値リストからアイテムを削除するにはどうすればよいですか?


16

リスト/選択オプションフィールドを持つコンテンツタイプを作成し、選択リストが機能するために必要に応じてキーと値のペアを入力しました。

データは登録されており、特定の条件が適用されなくなり、削除する必要があると判断されました。

ただし、上記の用語を削除しようとすると、次のエラーが表示されます。

Allowed values list: some values are being removed while currently in use.

明らかに、プロジェクトの存続期間中、値は変化します。リストされた用語にノードが関連付けられたら、アイテムを削除する実用的な方法は何ですか?

これは私が見つけることができる最も近いものについてです:

https://drupal.org/node/1653012

これは、d6プラグインと、私が頼りにしたくないいくつかのパッチトリックを参照しています。最終的にパッチを使用してそのフィールドの検証チェックを削除する必要があった場合、それらのアイテムが関連付けられているノード上で孤立したままにしておいても問題はありませんか?

更新、私はこの問題に再び直面しました。政府のクライアントは、Drupalのサイトを持っている過去7年間、選択リストに50の州と準州がありました。現在、ポリシーが変更され、テリトリーを含める必要がなくなりました。選択リストからアイテムを削除できることが重要であるため、私は賞金を提供しています。

選択リストからアイテムを削除できる安全なソリューションを探しています。ノードの合計コンテンツに関連してフィールド値がどのように格納されているかわからないため、そのソリューションがノードのいずれかを更新する必要があるかどうかはわかりません。

MySQLで実行するための純粋なSQLソリューションに満足しています。または、モジュールを探しています。


3
明らかに、プロジェクトの存続期間中、値は変化します。静的な選択リストの値は、プロジェクトの開始時に定義する必要があります。柔軟性が必要な場合は、静的リストの代わりに用語参照を使用する必要があります。静的リストは、性別(男性/女性)のようなもののためのものであり、物事に深刻な変化がなければ、すぐに変更される可能性はありません。存在する場合は、削除されずに追加されます。私はこの「間違い」を作った時はいつでも私はいつもバックアウトするための最良の方法は、データを手動でクエリを実行することです見つけた
クライヴ

1
このリストを動的にしたいですか?作成と削除が動的であること。
ママD

1
ええ、それは当時の意見にかかっていると思います-自動車メーカーは常に、私が構築するサイトのノードタイプまたはボキャブラリーになります。メーカーは車のカテゴリ(または誰かが修理する車のカテゴリ)であるため、コンテンツタイプというよりも分類法として最も理にかなっています。しかし、私はそれが解決しない知っている...私はDBに孤立したデータを残すことを警戒するだろう、それはあなたのサイトとどのようにそれが設定されています上にインストールされます正確に何を知らずに持っている可能性があり、そのどのような影響を与えると言うことは非常に難しい
クライヴ

1
views_bulk_operationsの何が問題になっていますか?
ドンキホーテ14年

1
あわや、これらの答えのどれもまだupvotesを持っていません:/
tenken

回答:


7

私は最近、次のアプローチでこのようなことをしました。

  1. 新しい許可値を追加します。
  2. 「アクティブな」値を構成する設定を追加します。
  3. フォーム上の表示から「非アクティブ」値を除外します。

例えば:

/**
 * Admin settings form
 */
function MODULE_admin_settings(){

  $form = array();

  // Select active preferences for display
  $field = field_info_field('field_preferences');
  $preferences = list_allowed_values($field);
  $form['field_preferences_active'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Active preferences'),
    '#options' => $preferences,
    '#description' => t('Select the preferences available for user selection.'),
    '#default_value' => variable_get('field_preferences_active', array()),
  );

  return system_settings_form($form);

}

/**
 * Implements hook_field_attach_form
 */
function MODULE_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {

  // Filter out inactive preferences
  if(isset($form['field_preferences'])){
    $preferences = variable_get('field_preferences_active', array());
    foreach($preferences as $key => $preference){
      // If this preference isn't checked, but is set in the field values, unset it.
      if(empty($preference) && isset($form['field_preferences'][LANGUAGE_NONE]['#options'][$key])){
        unset($form['field_preferences'][LANGUAGE_NONE]['#options'][$key]);
      }
    }
  }

}

これにより、参照用にレガシーデータが保持され、フォームが検証され、データの整合性が損なわれません。


1
このオプションは本質的に非破壊的(つまり、削除ではなく非表示)であり、おそらく、古いオプションを持つエンティティを処理するための最善のアクションコースを決定できるまでの最適な出発点です。
mpdonadio

3

私が知っているように、すべてのフィールドデータは、field_data_field_FIELDNAMEとfield_revision_field_FIELDNAMEの2つのテーブルに格納されます。そして、私はここで私の考えの確認を見つけました:https : //stackoverflow.com/a/7773117/1300562

したがって、不要なフィールド値を削除するには、上記のテーブルからこれらの値を削除し、許可された値のリストから削除する必要があります。

ステップ1。

$values_to_remove = array('value1', 'value2'); // an array of unnecessary values
$fieldname = 'FIELDNAME'; // name of your field. For example,
                          // 'territory' for field with machine name 'field_territory'
$entity_type = 'node'; // it's 'node' in your case, but it can be 'taxonomy_term' or something else

db_delete('field_data_field_' . $fieldname)
  ->condition('entity_type', $entity_type)
  ->condition('field_' . $fieldname . '_value', $values_to_remove)
  ->execute();

db_delete('field_revision_field_' . $fieldname)
  ->condition('entity_type', $entity_type)
  ->condition('field_' . $fieldname . '_value', $values_to_remove)
  ->execute();

ステップ2.
フィールド設定ページで不要なキーと値のペアを削除し、フォームを送信して変更を保存します。
その後、キャッシュは自動的にクリアされますが、ノードページで削除されたフィールド値が表示される場合は、キャッシュを手動でクリアしてください。

PS最近、私は同様の問題に直面しました、そして今、私はテキスト値のリストの代わりに「用語参照」または(さらに良い)「エンティティ参照」タイプのフィールドを使用することを好みます。参照フィールドを使用する場合、フィールドごとに個別の語彙を作成し、いつでも用語を簡単に作成/編集/削除できます。


フィールドが繰り返されている場合、それらのクエリは残りのデータのデルタを調整しません。
mpdonadio

1

まず最初に、フィールドに許可された値が指定されているかどうかを確認しますか?その場合、他のオプションは検証されません。そのため、最初に[フィールド設定]タブから値を削除してください。

または、2つのオプションがあります。


1。

ユーザーアカウントで使用中の許可値リストに入れたすべての値を削除します。たとえば、SQLクエリを実行してこれらを見つけることができます。

SELECT * FROM field_data_field_MYFIELDNAME WHERE entity_type = 'user' and value = 'MY VALUE'

または、許可された値のリストから削除したい値を持つユーザーアカウントを表示するユーザービューを作成します。


2。

フィールドから値を削除したくない場合、これはハックによって実現できます。

警告、これは生産のための提案された解決策ではなく、あなたが何をしているのかを知る必要があります!

  1. modules / field / field.moduleの検索と編集
  2. field_has_data()関数を見つけてreturn TRUE;、関数の最初の行に追加します。

    function field_has_data($field) {
      return FALSE; // HACK !!!
      $query = new EntityFieldQuery();
  3. 必要な値でフィールドを再保存します。
  4. すぐにハックを削除してください。

0

Views Bulk Operationsモジュールを使用して、実際にこれを実行できると思います。

  1. 置き換えるフィールドに新しいオプションを追加します。例:na | NA
  2. そのフィールドに含まれるノードをリストするビューを作成します
  3. そのビューに「一括操作:コンテンツ」フィールドを追加します
  4. 「エンティティ値の変更」および「利用可能なトークンの表示」をチェックします(表示値ですべてを選択)
  5. フィルター条件で変更するフィールドを追加し、フィルターを「公開」する
  6. そのビューにURLパスを設定します
  7. その表示ページに移動して変更します
  8. 次に、公開および操作機能を使用してフィールドオプションを変更します
  9. 完了

0

HLの回答の改善点がありますが、これが最善だと思います。

まとめると、選択フィールドに「古い」値が割り当てられているコンテンツに新しい値を割り当てる必要があります。

Views Bulk Operationsとは別に、Administration Viewsモジュールをインストールして有効にする必要があります。このモジュールでは、一括操作が有効になった状態ですぐに使用できるビューが既にあります(有効になったら管理者/コンテンツを参照してください)。次に:

1)管理/構造/ビューの編集「管理:ノード」ビューに移動します

2)上部の「追加->ページ」ボタンを使用して、ビューに新しいページ表示を追加します

3)新しいディスプレイへのパスを割り当てます:例admin / content / custom

4)選択フィールドに新しいフィルターを追加します。選択演算子「is one of」を選択し、削除するすべてのオプションを選択します

5)ビューを保存する

6)admin / content / customに移動するこれで、一括編集する必要があるすべてのコンテンツが表示されます(選択フィールドの値を変更します)

7)表の左側にある最初のチェックボックスをクリックしてすべての行を選択します(複数のページがある場合は、「このビューのすべてのX行を選択」というボタンも選択します)

8)「値の変更」操作を選択し、「実行」を押します

9)選択フィールドで、新しい値を選択して、削除する値を上書きします

10)その選択フィールドのチェックボックスを選択します

11)[次へ]をクリックすると完了です


0

Drupalの問題は、より深いデータの問題に基づいているようです。現在、減価償却リストの値を使用しているエンティティはどうなりますか?この質問は、Drupalから送信されたエラーメッセージの根本にあります。

州/準州の例を詳しく見てみましょう。あなたのクライアントは、長年にわたって州と領土を同じように扱うシステムを使用しており、州と領土の両方を含むノードの巨大なグループを構築しています。それからある日、領土の扱いを変える必要があり、地域を割り当てるためのドロップダウンに領土を含めるべきではないと決定する権限。すごい。標準フィルターを使用してすべてのテリトリーノードのリストをレンダリングするビューを作成し、Views Bulk Operationsを使用してすべてのリージョン値を変更します。領土の運命は非常に深刻な問題です。ソリューションには、テリトリーステータスを保持または再配置する方法が含まれている必要があります。「テリトリー」という名前の新しいリストフィールドを作成する必要がある場合があります

あなたは使用する必要がありますルールビューの一括操作をこれらの変更を実行するために。ルールについてよくわからない場合は、ルールがどのように機能するかについて時間をかけて学習してください。ルールを使用すると、トリガー、条件、およびアクションに基づいて情報を操作できます。ルールについて学習した後、探している答えが直感的に表示されることがあります。基本的に、すべてのテリトリーを対象とし、情報の本体からそれらを削除、再割り当て、名前変更、または分離するルールを作成する必要があります。これは、一括操作によってトリガーされます。ルールは、何らかの方法で領土の状態を保存でき、同時に状態のドロップダウンを「その他」または「N / A」ステータスに設定できる必要があります。これで十分です。さもないと...

再割り当てが完了したら、元のリストフィールドを変更してテリトリー名を削除するのは簡単な操作です。ただし、システムがまだリストの変更を許可していない場合は、新しいリストフィールドを作成し、ビューの一括操作とルールを使用して現在の状態値をすべて確認し、新しいリストに再割り当てする必要があります。ルールはビューの一括操作と連携して、関連するすべてのノードを対象とし、フィールド値に基づいてそれらに基づいて動作できます。ルールを使用すると、ノードのグループの既存のリストフィールドの値に基づいて新しいリストフィールドの値を設定するのは簡単です。

また、Drupalが操作で問題を起こした場合は、難しい代替案を検討する前に必ずキャッシュをフラッシュしてください。


0

クライアントがレガシーコンテンツに元の値を保持することを望んでいると思います。つまり、選択リストを変更すると、以前のデータは事実上すべて破壊されます。それが心配でなければ、他の答えはおそらくうまくいくでしょう。ただし、その場合、そのデータ履歴を失わずに選択リストを実際に変更することはできません。履歴データを許可するために、はるかに簡単な方法で、サイトの将来性を少し高めます-フィールド権限を使用することをお勧めします。

*静的データの代わりに分類法を使用して、その選択リストに新しいフィールドを設定します

*既存の選択リストのフィールド権限をVIEWとして設定しますが、admin以外のユーザーは編集できません

これにより、古いフィールドは表示および検索可能のまま(レガシーとしてのみ新しいタイトルを追加)、編集できません。これはもちろん、調整が必要なカスタム検索やビューなどに大きく依存します。

そのデータを削除し、履歴を削除し、最終的には壊滅的な結果になる可能性があるため、これを(それは聞こえるかもしれませんが面倒です)お勧めします。cssを使用して、編集ノードの古いフィールドを非表示にしたり、新しいコンテンツ(値が設定されていない場合)のためにフックを非表示にすることもできます。この方法では、そのレガシーコンテンツに対してのみ表示されます。

もちろん、カスタムワンオフモジュールを使用して、さらに一歩進んで、古い選択リストから新しい分類にデータをコピーすることもできます。


0

救助のための簡単なブラシスクリプト!フィールド設定を手動で変更する前に、フィールドデータとフィールドリビジョンテーブルを更新し、古い値を新しい値に置き換えます。

現在のフィールド設定に次のようなものがある場合:

&date=today|today
&date=last2days|last2days

それを次のものに置き換えたい:

date=today|today
date=last2days|last2days

まず、drushスクリプトを実行してから、管理UIでフィールド設定を変更します。

注:このコードは、マシン名のフィールド用field_foo_barです。

    $field_name = 'foo_bar';

    print "for {$field_name}...\n";

    replace_field("&date=today", "date=today", $field_name);

    replace_field("&date=last2days", "date=last2days", $field_name);

    function replace_field($old_value, $new_value, $field_name, $entity_type='node') {
      print "Replacing {$old_value} with {$new_value}...\n";
      $data_count = replace_options_data_field($field_name, $entity_type, $old_value, $new_value);
      $revision_count = replace_options_revision_field($field_name, $entity_type, $old_value, $new_value);
      print $data_count + $revision_count . " entries replaced.\n";
    }

    function replace_options_data_field($field_name, $entity_type, $old_value, $new_value) {
      $num_updated = db_update('field_data_field_' . $field_name)
        ->fields(array(
                   'field_' . $field_name . '_value' => $new_value,
                 ))
        ->condition('entity_type', $entity_type)
        ->condition('field_' . $field_name . '_value', $old_value)
        ->execute();
      return $num_updated;
    }

function replace_options_revision_field($field_name, $entity_type, $old_value, $new_value) {
  $num_updated = db_update('field_revision_field_' . $field_name)
    ->fields(array(
               'field_' . $field_name . '_value' => $new_value,
             ))
    ->condition('entity_type', $entity_type)
    ->condition('field_' . $field_name . '_value', $old_value)
    ->execute();
  return $num_updated;
}

0

kenorbの2番目の提案を使用し、Drupal 7.52、Profile2 7.x-1.3フィールドの値のリストを更新するように働きました。だからdrupal警告を受け取っていた場合:「許可された値のリスト:現在使用中にいくつかの値が削除されています。」

Drupalコアのルートディレクトリには、modulesというフォルダーがあり、編集するファイルはmodules / field / field.moduleにあります。これはコアファイルです。値の更新が完了したら、絶対に変更を元に戻す必要があります。サイトをオフラインにし、(drupal root)/modules/field/field.moduleの次のコードブロックを一時的に置き換えました

function field_has_data($field) {
  $query = new EntityFieldQuery();
  $query = $query->fieldCondition($field)
    ->range(0, 1)
    ->count()
    // Neutralize the 'entity_field_access' query tag added by
    // field_sql_storage_field_storage_query(). The result cannot depend on the
    // access grants of the current user.
    ->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT');

  return (bool) $query
    ->execute() || (bool) $query
    ->age(FIELD_LOAD_REVISION)
    ->execute();
}

正確に

function field_has_data($field) { 
    return FALSE; // hack 
    $query = new EntityFieldQuery();
}

そして、drupalは文句を言うのを止め、リストを変更することができました。(私の場合、大学を去ったが、アドバイザー、メンターなどとして学生の記録に関連付けられている価値のリストの教員です)

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