한 엔터티의 한 필드에서 하나의 항목을 프로그래밍 방식으로 삭제


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]); 경고를 피하기 위해 if (! empty (...)) {}에 array_values ​​()를 래핑해야했습니다.
user56reinstatemonica8

전체 필드를 지우고 싶을 때도 작동하며 "무결성 제약 조건 위반 : 1048 열 'field_duty_user_target_id'는 null 일 수 없음"
Darrell Duane

고마워요! node_load를 통해 필드 값을 변경하려고 시도했지만 작동하지 않았습니다. 따라서 이와 같이 엔티티 필드 값을 변경하면 확실히 작동합니다!
Артем Ильин

1

Drupal8 마이그레이션 정리의 일부로이 작업을 수행해야했습니다.

실험 후 델타에서 unset ()을 반복하고 사용하면 죽일 수 있음을 발견했습니다. 내 예는 태그를 제거하는 것입니다 (따라서 다른 필드에서 자주하는 것처럼 'value'가 아닌 '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);
Darrell Duane

1
올바른 방법은 $ node_wrapped-> field_name-> set ( "")입니다. $ wrapper-> save ()
chadpeppers
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.