プログラムでノードからフィールドを削除する方法は?


16

プログラムでノードからフィールドを削除するにはどうすればよいですか?hook_update_N内容をaaフィールドからカスタムテーブルに移動する移行があります。その移行後、同じ機能のフィールドを削除したいと思います。

フィールドの削除に対応するフィールドAPIはありますか?

編集、解決策:回答には実際のコードがないため、ここでフィールドを$ usersから自分のレコードに移動し、その後データベースからフィールドを削除しました。

function my_module_update_7005(&$sandbox) {
  $slice = 100;
  //Fetch users from database;
  if (!isset($sandbox['progress'])) {
    $sandbox['progress'] = 0;
    $sandbox['current_uid'] = 0;
    // We'll -1 to disregard the uid 0...
    $sandbox['max'] = db_query('SELECT COUNT(DISTINCT uid) FROM {users}')->fetchField() - 1;
  }
  if (empty($users)) {
    $sandbox["current_uid"] += $slice;
  }
  $users = db_select('users', 'u')
    ->fields('u', array('uid', 'name'))
    ->condition('uid', $sandbox['current_uid'], '>')
    ->range(0, $slice)
    ->orderBy('uid', 'ASC')
    ->execute();
  //Loop trough users;
  foreach ($users as $user) {
    $foo = new Foo();
    // Warning: drupal's fields return mixed values; e.g. NULL versus an int.
    $foo->debits = (int) $user->user()->field_credits["und"][0]["value"];
    $foo->save();

    $sandbox['progress']++;
    $sandbox['current_uid'] = $user->uid;
  }

  $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);

  // Remove the field.
  field_delete_field("field_credits"); //note that the name for Foo is field_foo
  field_purge_batch($sandbox['max']+1);//Drupal seems to have an offbyone problem.
}

回答:


29

field_delete_field($field_name)$field_name次のcron実行時に削除対象としてマークします。

field_purge_batchcronの実行時に削除したくない場合は、削除を実行できます。

編集: field_delete_field()他のバンドルからもフィールドを削除する必要がある場合に使用します。特定のバンドルからのみフィールドを削除する場合はfield_delete_instance()、@ Cliveで言及されているように使用する必要があります。


4
慎重に、それはまた、知っておくに:)グッド添付される可能性があります任意の他のバンドルからフィールドを削除しますfield_purge_batchけれども
クライヴ

@Clive:そうです、すべてのバンドルからフィールドを削除します。修正していただきありがとうございます:)私は答えを編集しました。
-AjitS

つまり、すべてのバンドルからフィールドを完全に削除したかったのです。しかし、警告は良いです。ありがとう。
12

1
field_delete_instance()がその方法です。
ライアンマクベイ

field_purge_batch()は実際には、渡されるバッチサイズと同じ数のフィールドアイテムのみを削除します。これは、フィールドにいくつかの項目しかない場合に役立ちます。そのため、フィールドインスタンスを完全に削除するために、cronがそれを削除するのを待つ必要はありません。フィールドに多くの値がある場合は、バッチサイズを大きくしすぎないようにしてください(名前の「バッチ」は、それ自体がバッチ処理を行うことを意味せず、単一のバッチを実行することを意味します)あなたがそれを頼むのと同数のアイテムの); PHPメモリまたは制限時間に達する可能性があります。
エルケブロック

24

特定のバンドルからフィールドを削除するには、使用できます field_delete_instance()

フィールドインスタンスとそのデータに削除のマークを付けます。

例:

function my_module_update_7001() {
  if ($instance = field_info_instance('node', 'field_name', 'page'))  {
    field_delete_instance($instance, TRUE);
    field_purge_batch(1);
  }
}

システムからフィールドを完全に削除するには、次を使用できます。 field_delete_field()

フィールドとそのインスタンスおよびデータに削除のマークを付けます。

例:

function my_module_update_7001() {
  field_delete_field('field_name');
  field_purge_batch(1);
}

フィールド/インスタンスには削除のマークが付けられているだけで、その後のcron実行中にデータは実際にパージされます。手動で削除するには、次を実行します。

field_purge_batch(1);

1
呼び出しfield_delete_field()field_purge_batch()動作している間、field_config_instanceとにレコードを保持しますfield_config。何故ですか?
12

値が1のfield_purge_batchを呼び出すと、すべてのフィールドデータが削除される理由がわかりません。コードを正しく理解していれば、$ batchsizeエンティティのフィールドデータを取得し、その場所に残します(つまり、関数を再帰的に呼び出すことはありません)。すべてのデータがなくなっているかどうかを確認するのは呼び出し側次第で、そうでない場合は関数の呼び出しを続けます。しかし、基本的に何かを誤解しているのかもしれません。
エルケブロック

実際、field_ui.admin.incのこのコメントは、これを説明する上で非常に役立ちます。// cronでフィールドがパージされます。ただし、フィールドモジュールは、提供されたフィールドタイプが//完全にパージされるまでフィールドで使用されている場合、モジュールを無効にすることを防ぎます。フィールドに最小限のコンテンツがある場合、またはフィールドにコンテンツがない場合、field_purge_batch()の1回の呼び出しで//フィールドがシステムから削除されます。//この基準を満たすインスタンスを削除するときに管理者がcronの実行を待つ必要がないように、//バッチ制限を低くしてこれを呼び出します。
エルケブロック

@Clive、私はあなたがアドバイスであると暗黙のうちに信じていますが、if条件で宣言するのがいかに奇妙に見えるかを乗り越えることはできません。それは意図的ですか?私は言及してい$instance = field_info_instance('node', 'field_name', 'page')ます。代わりに$instance = field_info_instance('node', 'field_contact', 'job');if文を削除するべきではありませんか?
cdmo

1
@cdmoは「状態の割り当て」と呼ばれ、問題あります。しかし、Drupalコアは最新バージョンであってもそれを自由に使用しているため、少なくとも先例があります。正直に言うと、これは5年前で、少し賢くなりました。使用しないか、何らかの理由で割り当てをラップします(たとえばif ( ($foo = $bar) ) {、意図が明白で、field_delete_instancenullをチェックしないためifステートメント自体が必要です
Clive

5

@berkesの質問に答えるには:

field_delete_field()フィールドに削除のマークを付けて、次のcronの実行時に削除されるようにします。しかし、それはありません上の休暇データをfield_config_instance落としフィールドについて。cronを実行field_purge_batch()するか、このデータを削除しませんfield_config_instanceする1と、フィールドに対して削除された列が設定されている場合でも、テーブル。

私にとってはfield_delete_instance()field_purge_batch()にとっては、パージされたフィールドごとにが -データベースからフィールドを即座に削除し(cronを必要とせず)、field_config_instanceフィールドデータのテーブルを削除します(削除されたフィールド)。

解決策は次のとおりです。

/**
 * Implements hook_uninstall().
 */
function hook_uninstall() {
  // Delete all fields for all xyz entity bundles.

  // Retrieve all bundles for an entity.
  $bundles = field_info_bundles('XYZ'); // The name of your entity type, for example, 'node'.
  foreach ($bundles as $bundle => $properties) {

    // Retrieve all the fields for a given bundle.
    $instances = field_info_instances('XYZ', $bundle);
    foreach ($instances as $instance) {
      field_delete_instance($instance, TRUE);
      field_purge_batch(1);
    }
  }
}

フィールドAPIがクリーンアップ操作を実行する必要があることを示すため、TRUEon field_delete_instance()に注意してください。


このコードの使用方法は?コンテンツタイプからタイトルフィールドを削除したい
-Umair
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.