Hangisi daha fazla performans gösterir: entity_metadata_wrapper veya field_get_items?


10

Varlıklardan değer almanın iki yolu vardır:

  • field_get_itemsBir alanın değerini kullanın ve alın
  • entity_metadata_wrapperBir alanın değerini kullanın ve alın

Her ne kadar entity_metadata_wrapperdil farklarını soyutlasa da, API'si bazen PHP 5.3 kullanırken hala garip. Örneğin, uzun bir metin alanının değerini almak genellikle bu yola gider:

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

Neyse ki, PHP 5.4 bu sözdizimini destekler: print $wrapper->field->value()['safe_value'];.

Ama sorum daha çok performansla ilgili. İkisi de nasıl çalışıyor? Her değer talep ettiklerinde veritabanını sorguluyorlar mı? Her entity_metadata_wrapperşeyi bir kerede ister mi? ( field_get_itemTek değerli alımlar için daha uygun hale getirme .)

Drupal kaynağına derinlemesine dalmaya yetecek kadar cesur değilim.


1
field_view_field()bir alanı oluşturmak içindir. Bir alanın değerini alma işlevi field_get_items () şeklindedir .
kiamlaluno

Ve field_get_items()sıfır veritabanı yükü bu yüzden bu oldukça açık ve kapalı bir dava düşünüyorum :)
Clive

@Clive nasıl gelir field_get_items()sıfır veritabanı yükü oluşur? Verilerini bir yere götürmeli, değil mi?
Florian Margaine

Ayrıca, entity_metadata_wrapperperformans açısından nasıl çalıştığını bilmekle gerçekten ilgileniyorum .
Florian Margaine

2
Tamamen dolu bir obje nesnesini geçersiniz, field_get_items()böylece ek yük zaten gerçekleşmiştir ... D7'de dürüst olmak gerekirse biraz boğulmuş bir rota var
Clive

Yanıtlar:


12

Kısa cevap: field_get_items () entity_metadata_wrapper () 'dan daha performanslıdır.

Bu işlevlerin kodunu kontrol edin:

Her ikisi de, zaten veritabanından yüklenmiş olan varlığın üzerinden geçmenizi gerektirir . Örneğin:

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

veya daha önce önerdiğiniz gibi:

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

Bu örneklerin her ikisi de, zaten sizin için mevcut olan bir değeri elde etmeye çalışırken aptal mantık nedeniyle beni rahatsız ediyor, ancak birçok durumda kesinlikle yararlı.

Sadece yapabilirsin, print $node->field_my_field_name[LANGUAGE_NONE][0]['value'];ancak alanın bir değeri yoksa PHP bildirim hataları atar, çünkü var olmayan dizilere erişmeye çalışıyorsun (yani [LANGUAGE_NONE][0]['value']). Kendimi son zamanlarda oldukça sık yapıyor:

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

Yapmaktan çok daha temiz:

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'];
}

Eğer koda bakarsanız field_get_items()), alanın dizisinin akıcı dilde veri içerdiğinden ve sonra döndürdüğünden emin olmaktan başka bir şey yapmadığını göreceksiniz. Bu nedenle, bu kadar küçük bir işlevi çalıştırmanın yükü göz ardı edilebilir, ancak performansla gerçekten ilgileniyorsanız, verilerin var olup olmadığını kendi kontrolünüzü yapabilir ve sonra yazdırabilirsiniz.

Düzenleme: yana field_get_items()ishal field_language()bunu zaten $ kişilik-> dil var, sadece kendi süper performant fonksiyonu yazabiliriz biliyorsanız aslında, sadece bu yüzden, dili kontrol daha büyük bir performans isabet olurdu:

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

Tamam, bu kontrollerden ayrı olarak, bunları kaç kez kullanırsam kullarım bir kez yüklenir? Varlık referanslarını kullansam bile?
Florian Margaine

Evet, bu aslında D7'deki varlık API'sının oldukça havalı bir özelliğidir. Bir varlığı yükledikten sonra, bu istek süresince önbelleğe alınır. Yani, $node = node_load(123);1 komut dosyasında yaparsanız ve bunu başka bir yerde yaparsanız, tam bir nesne yükünün ve derlemesinin performans yüküne maruz kalmazsınız - Drupal bu değişkene mevcut varlığın bir kopyasını atar. Yeni bir kopya yüklemek istiyorsanız $reset = TRUE, varlık yükleme işlevine geçmeniz gerekir . Ayrıca, süper performanslı bir alıcıyla ilgili düzenlemelerime bakın.
Charlie Schliesser

1
if (isset($node->field_my_field_name[LANGUAGE_NONE]) && isset($node->field_my_field_name[LANGUAGE_NONE][0])) {gerekli değildir isset($node->field_my_field_name[LANGUAGE_NONE][0], yeterlidir.

@chx Kabul ediyorum, ancak isset($node->field_my_field_name[LANGUAGE_NONE])dil boş bir alanda ayarlanmayacağından öyle olmaz mıydı? Sanırım delta / [0]gereksiz.
Charlie Schliesser

1
@GilesB, daha fazla veritabanı sorgusu genellikle birleştirmelerden daha iyi değildir. İstekli yükleme bir optimizasyon tekniğidir. Ama bunu söyleyerek bile, varsayımınızın yanlış olduğunu düşünüyorum ve EntityMetadataWrapper muhtemelen daha yavaş, ama kullanmak çok daha güzel. Bu aynı zamanda mikro optimizasyon OP'nin Drupal ile çalışırken düşünmesi gerekmiyor.
Nicholas Ruunu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.