1つのエンティティの1つのフィールドから1つのエントリをプログラムで削除する


13

特定のエンティティから複数エントリフィールドの特定のフィールドエントリをプログラムで削除する適切な方法は何ですか?(つまり、フィールドタイプまたはインスタンスおよびエンティティタイプではなく、特定のフィールドおよび特定のエンティティです)

私が調べたいくつかの可能性がありますが、うまくいきません:

  • でエンティティを読み込み、entity_load()フィールドエントリを= nullまたは= array()に設定してから保存しfield_attach_update()ます。これは私が見つけた最も近いものですが、データベースにゾンビnullフィールドエントリを残し、フォームが保存されて起動できるようになるまでhook_field_is_empty()hook_field_is_empty()= nullまたは= array()がフラグを立てるように設定されるまで)フォームの空白行として表示されます空として)。
  • でエンティティをロードし、entity_load()キーでフィールドエントリを設定解除し、で保存しfield_attach_update()ます。これは何もしないようです-Drupalは、エントリが存在しないことを、変更しないためのサインとして解釈しているようです。(奇妙なことに、このアプローチを試みると、クエリ時間の有効期限が最大になることもあります)
  • field_attach_delete() -これはあまりにも鈍い:エンティティのすべてのフィールドを殺す
  • field_purge_data() -より良いが、それでも鈍い:特定のエントリではなく、フィールドのすべてのエントリを殺す

そのため、明確にするために、複数のエントリを持つフィールドを持つエンティティを検索(およびロード)し、そのフィールドで削除する必要がある特定のエントリを検索するコードを用意しました。エンティティの他のエントリや他のフィールドに触れることなく、そのエントリを完全に削除したい。

回答:


24

エンティティAPIモジュールに依存できる場合は、次のようなコードを使用できるはずです。

// Load some entity.
$entity = entity_load_single($entity_type, $id);

// Remove the field value.
unset($entity->field_FIELD_NAME[LANGUAGE_NONE][$index]);

// Reset the array to zero-based sequential keys.
$entity->field_FIELD_NAME[LANGUAGE_NONE] = array_values($entity->field_FIELD_NAME[LANGUAGE_NONE]);

// Save the entity.
entity_save($entity_type, $entity);

2
これはうまくいきました!おかげで、私のゾンビの問題は根絶されました。他の人の時間を節約するかもしれないいくつかの注意:エンティティAPIをRC2に更新する必要がありました。動的フィールド名を使用していたため、設定解除行にはunset($ entity-> {$ field_name} [LANGUAGE_NONE] [$ index])のような中括弧が必要でした。警告を避けるために、array_values()をif(!empty(...)){}でラップする必要がありました
user56reinstatemonica8

これも、あなただけのフィールド全体をクリアしたい場合は働き、そして恐ろしい回避「整合性制約違反を:1048列『field_duty_user_target_id』はNULLにすることはできません」
ダレルデュアン

どうもありがとう!node_loadを介してフィールド値を変更しようとしましたが、機能しませんでした。したがって、このようにエンティティフィールドの値を変更しても、確実に機能します!
АртемИльин

1

Drupal8移行クリーンアップの一部としてこれを行う必要がありました。

いくつかの実験の後、デルタで反復してからunset()を使用すると、デルタを強制終了できることがわかりました。私の例では、タグを削除しました(したがって、他のフィールドでよく使用する「値」ではなく、「target_id」を検索します。

/**
 * Removes a term from a field.
 *
 * @return bool
 *   success
 */
private function removeTerm(\Drupal\node\NodeInterface $object, \Drupal\taxonomy\TermInterface $term, $field_name) {
  // Check if tag value exists already.
  // Remember they may be multiples.
  /** @var @var \Drupal\Core\Field\FieldItemList $field_values */
  $field_values = $object->get($field_name);
  foreach ($field_values as $delta => $field_value) {
    if ($field_value->getValue()['target_id'] == $term->id()) {
      unset($field_values[$delta]);
      return TRUE;
    }
  }
  return FALSE;
}

そしてその後、成功すれば、 $object->save();


0

Drupal 8の場合、エンティティからフィールドを削除するには:

$entity = Node::load($nid);
unset($entity->field_name);

これにより、ContentEntityBaseからマジックメソッド__unset()が呼び出されます。

public function __unset($name) {
    // Unsetting a field means emptying it.
    if ($this->hasField($name)) {
        $this->get($name)->setValue([]);
    }
    // For non-field properties, unset the internal value.
    else {
        unset($this->values[$name]);
    }
}

変更を永続化するには、電話する必要があることを忘れないでください

$entity->save();

すべての変更を行った後。


-1

これはより良い方法です:

> $user = user_load($user->uid); 
> $user_wrp = entity_metadata_wrapper('user', $user);
> $user_wrp->{'field_data_multiple'} = array();

-2

現在の好ましい方法はentity_metadata_wrapperを使用します

$node_wrapped = entity_metadata_wrapper('node', node_load($nid));

unset($node_wrapped->$field_name[$index];

これは私が見たEMWに関する最高のチュートリアルですhttp://deeson-online.co.uk/labs/programatically-access-field-data-using-entitymetadatawrapper-drupal


これは機能しませんでした。私は運のないこのように試してさえいました。$ wrapper = entity_metadata_wrapper( 'node'、$ duty); unset($ wrapper-> field_duty_user); $ wrapper-> save(); node_save($ duty);
ダレルデュアン14

1
正しい方法は$ node_wrapped-> field_name-> set( ""); 次に$ wrapper-> save()
chadpeppers 14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.