entity_metadata_wrapper 또는 field_get_items 중 성능이 더 좋은 것은 무엇입니까?


10

엔터티에서 값을 가져 오려면 다음 두 가지 방법이 있습니다.

  • field_get_items필드의 값을 사용 하고 얻습니다
  • entity_metadata_wrapper필드의 값을 사용 하고 얻습니다

entity_metadata_wrapper언어 차이를 추상화 했지만 , 특히 PHP 5.3을 사용하는 경우 API가 여전히 어색합니다. 예를 들어, 긴 텍스트 필드의 값을 얻는 것은 일반적으로 다음 경로를 따릅니다.

$field = $wrapper->field->value();
print $field['safe_value'];

다행히도 PHP 5.4는 다음 구문을 지원합니다 print $wrapper->field->value()['safe_value'];.

그러나 내 질문은 성능에 더 관심이 있습니다. 둘 다 어떻게 작동합니까? 그들은 값을 요청할 때마다 데이터베이스를 쿼리합니까? entity_metadata_wrapper한 번에 모든 것을 요청 합니까 ? ( field_get_item단일 값 검색에 더 적합하게 만들기 )

드루팔 소스를 깊이 파고들 정도로 용감하지 않습니다.


1
field_view_field()필드를 렌더링하기위한 것입니다. 필드 값을 가져 오는 함수는 field_get_items () 입니다.
kiamlaluno

그리고 field_get_items()나는 그 :) 꽤 개방 및 폐쇄의 경우 생각 때문에 초래 데이터베이스 오버 헤드를 제로
클라이브

@Clive 어떻게 field_get_items()데이터베이스 오버 헤드 가 발생하지 않습니까? 어딘가에 데이터를 가져와야합니까?
Florian Margaine

또한 entity_metadata_wrapper성능 측면 에서 어떻게 작동 하는지 알고 싶습니다 .
Florian Margaine

2
field_get_items()오버 로드 가 이미 발생 했으므로 완전히로드 된 엔터티 개체를 전달했습니다. 정직하게 D7에서 약간 교살 된 경로입니다
Clive

답변:


12

짧은 대답 : field_get_items ()는 entity_metadata_wrapper ()보다 성능이 뛰어납니다.

다음 기능에 대한 코드를 확인하십시오.

둘 다 데이터베이스에서 이미로드 된 엔티티를 전달해야 합니다 . 예를 들면 다음과 같습니다.

$node = node_load(123);
$items = field_get_items('node', $node, 'field_my_field_name');
print $items[0]['value'];

또는 이미 제안했듯이 :

$wrapper = entity_metadata_wrapper('node', $node);
$field = $wrapper->field_my_field_name->value();
print $field['safe_value'];

이 두 인스턴스는 이미 사용 가능한 값을 얻으려는 어리석은 논리 때문에 나를 귀찮게하지만 많은 경우에 확실히 유용합니다.

당신은 할 수 print $node->field_my_field_name[LANGUAGE_NONE][0]['value'];있지만 필드에 값이없는 경우에 당신이 존재하지 않을 수 있습니다 액세스 배열 (예에 노력하고 있기 때문에 즉, PHP 고지 오류를 던질 것이다 [LANGUAGE_NONE][0]['value']). 나는 최근에 이것을 자주하는 것을 발견했다.

if ($field = field_get_items('node', $node, 'field_my_field_name')) {
  print $field[0]['value'];
}

이것은 일보다 훨씬 깨끗합니다.

if (isset($node->field_my_field_name[LANGUAGE_NONE]) && isset($node->field_my_field_name[LANGUAGE_NONE][0])) {
  print $node->field_my_field_name[LANGUAGE_NONE][0]['value'];
}

코드를 살펴보면 field_get_items())더 이상 아무것도하지 않는 것을 알 수 있습니다. 필드 배열에 현재 언어의 데이터가 있는지 확인한 다음 반환하십시오. 따라서 작은 기능을 실행하는 오버 헤드는 무시할 수 있지만 실제로 성능에 관심이 있다면 데이터가 있는지 직접 확인한 다음 인쇄 할 수 있습니다.

편집 : 이후 field_get_items()실행 field_language()당신은 이미이 $로 entity> 언어가 존재, 당신이 당신 자신의 최고 성능이 좋은 기능을 쓸 수 있습니다 알고있는 경우에 실제로, 너무, 언어를 확인하는 것보다 더 큰 성능 저하가있을 것입니다 :

function my_super_performant_field_value_getter($entity, $field_name) {
  return isset($entity->{$field_name}[{$entity->language}]) ? $entity->{$field_name}[{$entity->language}] : FALSE;
}

좋아, 그 검사와는 별개로, 몇 번이나 사용하더라도 엔티티가 한 번로드됩니까? 엔티티 참조를 사용하더라도
Florian Margaine

예, 이것은 실제로 D7의 엔티티 API의 매우 멋진 기능입니다. 엔터티를로드하면 해당 요청 기간 동안 엔터티가 캐시됩니다. 따라서 $node = node_load(123);하나의 스크립트에서 다른 곳에서 다시 수행하면 전체 오브젝트로드 및 빌드의 성능 오버 헤드가 발생하지 않습니다. Drupal은 해당 변수에 기존 엔티티의 사본을 지정합니다. 사본 을로드 $reset = TRUE하려면 엔티티로드 기능 으로 전달해야 합니다. 또한 성능이 뛰어난 게터에 대한 편집 내용을 참조하십시오.
Charlie Schliesser 2016

1
if (isset($node->field_my_field_name[LANGUAGE_NONE]) && isset($node->field_my_field_name[LANGUAGE_NONE][0])) {필요하지 않습니다, isset($node->field_my_field_name[LANGUAGE_NONE][0]충분합니다.

@chx 동의 isset($node->field_my_field_name[LANGUAGE_NONE])합니다. 언어가 빈 필드에 설정되지 않기 때문에 그렇지 않습니까? 나는 그것이 델타 /라고 생각합니다 [0].
Charlie Schliesser

1
@GilesB에서는 더 많은 데이터베이스 쿼리가 조인보다 낫지 않은 경우가 많습니다. 빠른 로딩은 최적화 기술입니다. 그러나 심지어는 귀하의 가정이 거짓이며 EntityMetadataWrapper가 느리다고 생각하지만 사용하기가 훨씬 좋습니다. 이것은 또한 Drupal과 작업 할 때 OP가 생각할 필요가없는 미세 최적화입니다.
Nicholas Ruunu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.