Performans: Tüm ürün türlerinin ürün listelerine list.phtml Envanter Stok Düzeyleri ekleyin


12

TL; DR , Gereksinim, Magento'nun çerçevesine uygun performans göz önünde bulundurularak, kategori ürün listeleme sayfasında envanter stok seviyesinin görüntülenmesi, ek sorguların / hafızanın az olması ile gösterilmektedir.


Vinai Kopp'un ölçeklenebilirlik için önyükleme hakkındaki makalesini okuduktan sonra .

Envanter stok düzeylerini, kategori ürün listeleme sayfalarına ( list.phtml ), performans paketleri için birkaç sorgu / yük ekleyerek eklemenin en iyi yolu nedir ?

Birkaç yaklaşımın farkındayım:

afterLoad ()media_gallery ek sorgular olmadan dahil etmeile iyi çalışıyor gibi görünüyor, ancak aynı yaklaşımı envanter ile uygulamakta başarılı olamadım .

$attributes = $_product->getTypeInstance(true)->getSetAttributes($_product);
$media_gallery = $attributes['media_gallery'];
$backend = $media_gallery->getBackend();
$backend->afterLoad($_product);

product_idÖrneğin bir anahtarla koleksiyona paralel olarak gerekli verileri toplamak için SQL'i yönlendirin . Ancak çerçeve içinde daha fazla araç aramak.

Şu anda sadece stock_itemüzerinden nesne yüklüyorum :

$_product->load('stock_item')->getTotalQty(); Hangi işe yarıyor, ancak koleksiyondaki tüm ürünlerin envanter stok toplamlarını almak için daha fazla sorgu eklendiğini fark ediyorum.

...

__EAV_LOAD_MODEL__ (Mage_Catalog_Model_Product, id: stock_item, attributes: NULL)
__EAV_LOAD_MODEL__ (Mage_Catalog_Model_Product, id: stock_item, attributes: NULL)
__EAV_LOAD_MODEL__ (Mage_Catalog_Model_Product, id: stock_item, attributes: NULL)

...

garip bir şekilde, bu işe yarıyor. Sihir Mage_Eav_Model_Entity_Abstract-> load ($ object, $ entityId, $ attributes) içinde gerçekleşir. $ Öznitelikleri boşsa, loadAllAttribute ($ object) öğesini çağırır. $ Product-> load ('blah'), 'media_gallery' dahil olmak üzere tüm eksik özellikleri yükleyecektir - William Tran 19 Kasım 14 '14 4:45

Önceden yüklenmiş koleksiyona gerekli değerleri ekleyin.

Katman / filtredeki üst düzey üretim koleksiyonuna ihtiyaç duyulan verileri eklemenin bariz basit yaklaşımı en iyi yaklaşım gibi görünmektedir.

Ben fark ediyoruz gözlemci yaptılar addInventoryDataToCollection () içinde Mage_CatalogInventory_Model_Observer böyle sesler böyle ulaşmak, ancak uyumlu olacak şekilde görünmüyor özel modülleri gözlemci yöntemi ekleme söyledi.

<events>
    <catalog_product_collection_load_after>
        <observers>
            <inventory>
                <class>cataloginventory/observer</class>
                <method>addInventoryDataToCollection</method>
            </inventory>
        </observers>
    </catalog_product_collection_load_after>
</events>

Sonuç:

Uyarı: 71. satırdaki /app/code/core/Mage/CatalogInventory/Model/Resource/Stock/Item/Collection.php içindeki foreach () için geçersiz argüman sağlandı


1
İyi soru boomer
Amit Bera

Yanıtlar:


4

Burada asıl mesele önyükleme değil, doğruluk. Bir ürün koleksiyonu için stok miktarını elde etmek nispeten kolaydır:

$products = Mage::getModel('catalog/product')->getCollection()
    ->addCategoryFilter($_category);
$stockCollection = Mage::getModel('cataloginventory/stock_item')
    ->getCollection()
    ->addProductsFilter($products);

Şimdi iki sorgu ile ihtiyacınız olan tüm bilgilere sahipsiniz. 'product_id' => 'stock'İlişkisel bir dizi kullanarak ve bir alıcı yazarak düzeltilebilen birbirleriyle ilişkilendirmek zordur . Ayrıca, addProductsFilter optimize edilebilir:

public function addProductIdsFilter(array $productIds)
{
    if(empty($productIds) {
        $this->_setIsLoaded(true);
    }
    $this->addFieldToFilter('main_table.product_id', array('in' => $productIds));
    return $this;
}

Bu size tür kontrolü ve dizi klonlama kazandırır.

Şimdi sorun HTML önbelleğini engelle. Bu kategori sayfasının, içerdiği üründe herhangi bir hisse senedi güncellendiğinde temizlenmesi gerekir. Bildiğim kadarıyla, bu standart değildir, çünkü sadece bir stok durumu değişikliği bir ürün içeren bir kategori sayfasını (veya daha doğrusu bir görünürlük değişikliğini) temizler. Bu nedenle, en azından cataloginventory_stock_item_before_saveve belki birkaç tanesini gözlemlemeniz ve o kategori sayfası için blok html önbelleğini (ve FPC önbelleğini) temizlemeniz gerekir.


Son noktanız, hisse senedi verilerini almak için ek talepte bulunmamızın nedenidir. Hızlı hareket eden ürünlere sahip kategorileriniz varsa, önbelleğe aldığınız zaman zamanının çoğunu temizlenir / geçersiz kılınır. bir kategori sayfası önbelleğini temizlememiz gereken tek zaman, bir ürünün o kategoriden kaldırılmasıdır. En etkili uygulamayı duruma göre incelemeniz gereken tek bir sihirli çözüm yoktur. İsterseniz stok verilerini önbelleğe alabilirsiniz, böylece tüm sayfa yerine yalnızca yıkamadan sonra yeniden oluşturulması gerekir.
john-jh

DOM'u güncellemek için JavaScript verilerini kullanarak hisse senedi verilerini şimdi yaptığınız gibi uygularsanız, bunu kendi önbellek anahtarına sahip bir blok kullanarak yazabilir ve yalnızca stok verilerini geçersiz kılabilirsiniz. Durumunuz için böyle yapardım ve ESI tabanlı bir FPC kullanmıyorum, ancak istek işlemcide yumruk bloklarını delebilen bir şey. Sadece yönlendirici biti için değil, aynı zamanda sayfa başına sadece bir php tercümanı gerektirdiği için. Ne zaman olursa olsun bir makine baskı altına gelirse, php tercüman en Cpu yoğun kaynaktır. Bu güzel bir haftasonu projesi gibi daha fazla ses çıkarmaya başlıyor ;-)
Melvyn

3
Bu, uygulamayı ve potansiyel sorunları ve darboğazları gerçekten düşünmeniz gereken yerlerde işi gerçekten ilginç kılan şeylerdir. Meydan okurcasına tek bir PHP işlemiyle nereden geldiğinizi anlıyorum, şu anda bu bizim için bir sorun değil ama ölçeklendirirken nasıl bir etki yaratacağını görebiliyorsunuz. Sayfada görüntülenen stok değerleri kritik bir işlevsellik değildir, bu nedenle yüklemeden sonra kullanıcıyı etkilemeden ikincil kaynak olarak yükleriz. Ürün listesinde utanç verici bir stok değil, varsayılan bir özellik.
john-jh

1
Evet, şimdi bunu Redis'ten doğrudan getirip php'yi kesmek için kullanıyorum. Burada Yichun Zhang'ın açık Resty ile ilgili bazı ilginç çalışmaları var .
Melvyn

2

Zaten kabul ettiğinizi ve şüphesiz şimdiye kadar bir şey uyguladığınızı görüyorum, ancak ne kadar yakın olduğunuzu belirtmek istiyorum, ancak addInventoryDataToCollection()yapılandırma dosyasını yanlış tanımladığınız veya magento'nun çok farklı sürümlerini kullandığımız anlaşılıyor. Benim kopyamda CatalogInventory/etc/config.xmlçağrılan farklı bir yöntem varcatalog_product_collection_load_after

 <catalog_product_collection_load_after>
    <observers>
        <inventory>
            <class>cataloginventory/observer</class>
            <method>addStockStatusToCollection</method>
        </inventory>
    </observers>
 </catalog_product_collection_load_after>

addInventoryDataToCollection() denir <sales_quote_item_collection_products_after_load>

Kaynağı addStockStatusToCollection():

public function addStockStatusToCollection($observer)
{
    $productCollection = $observer->getEvent()->getCollection();
    if ($productCollection->hasFlag('require_stock_items')) {
        Mage::getModel('cataloginventory/stock')->addItemsToProducts($productCollection);
    } else {
        Mage::getModel('cataloginventory/stock_status')->addStockStatusToProducts($productCollection);
    }
    return $this;
}

require_stock_itemsKoleksiyondaki bayrağı yüklenmeden önce ayarlayabilir , muhtemelen kategori listesinin arkasındaki blok için o kadar kolay olmayabilir veya Mage::getModel('cataloginventory/stock')->addItemsToProducts($productCollection)zaten yüklendikten sonra koleksiyonda manuel olarak arama yapabilirsiniz . addItemsToProducts()sizin için tüm StockItems'leri alır ve bunları ProductCollection'ınıza ekler

public function addItemsToProducts($productCollection)
{
    $items = $this->getItemCollection()
        ->addProductsFilter($productCollection)
        ->joinStockStatus($productCollection->getStoreId())
        ->load();
    $stockItems = array();
    foreach ($items as $item) {
        $stockItems[$item->getProductId()] = $item;
    }
    foreach ($productCollection as $product) {
        if (isset($stockItems[$product->getId()])) {
            $stockItems[$product->getId()]->assignProduct($product);
        }
    }
    return $this;
}

1

Vernik veya FPC kullanıyor musunuz yoksa gelecekte planlıyor musunuz?

Ürün listelerinde gerekli olan delik zımba / ESI isteklerinin miktarıyla bulduğumuz, neredeyse farklı bir yaklaşım için önbelleğe almanın değerine değmezdi.

Ürünler için stok verilerini almak üzere özel bir denetleyiciye AJAX isteği kullanan bir web sitesine bir çözüm uyguladık ve javascript DOM güncellemelerini yönetiyor. Stok verileri için ek istek ~ 100 ms sürer, bu da toplam (görünür) sayfa yükleme süresini etkilemez. Astarlanmış FPC'nin sayfa isteğini 100 ms altına düşürmesiyle, ürün listelerinde stok verilerini görüntülemek için düşük performans yükü olan bir hızlı siteye sahip olduğunuzu bir araya getirin.

Şablon akıllıca yapmanız gereken tek şey, her ürün sarmalayıcı html'ye productId eklemektir, böylece javascriptiniz her ürün için hangi stok verilerinin uygulanacağını bilir.

Gerçek stok verileri için ek önbellekleme tekniklerine bakarsanız, her istek üzerine Mage'yi başlatmak / veritabanına ulaşmak zorunda kalmadan 100ms'in altına düşebilirsiniz.

Bu, aradığınız şeyin çizgisi boyunca değilse, ancak gereksinimlerimize karşı ölçeklenebilirlik ve performans için en iyi yaklaşım olduğunu gördük.


2
Dağıtma kaos maymun ve önbellek depolama üzerine düştüğünde ne olduğunu görün. Soru özellikle önbelleğe güvenmemekten bahsediyor. Müşteriyi FPC'nin BuiltIn / MomsBasement şablonlarını çok daha fazla düzeltmeyeceğine ikna etme işimizi böyle cevaplar.
Melvyn

Performans ve çözüm olarak FPC / Varnish'i önerdiğimi düşünüyorsanız cevabımı gerçekten yanlış anlıyorsunuz. FPC / Vanish kullanıyorlarsa veya düşünüyorlarsa, delik delme / ESI taleplerini azaltmak için bu yaklaşımı araştırmaları gerektiğini belirttim. İhtiyaç duyduğumuz hisse senedi verilerini 100ms'in altında önbellekten ayrılmadan alıyoruz.
john-jh

Aynı verileri ESI kullanarak aynı anda elde edersiniz. ESI ile yaklaşımınız temelde farklıdır. Böylece, herhangi bir önbellek olmadan aynı verileri daha kısa sürede elde edebilirsiniz. JSON'u geri göndermek için başka bir yönlendiriciden geçmek yerine, JavaScript'te DOM'yi vb. Güncelleyen bir stok dizisi yazıyorsunuz. Cehennem, isterseniz JSON'a koyun, yönlendiriciyi kesin.
Melvyn

1
Önbelleğe alma kullanılacaktır, ancak soru daha çok performans optimizasyonları satırındadır. Bazı arka plan: magento.stackexchange.com/questions/13957/… (önbellek yok / neredeyse hiç yok) Yanıt için teşekkürler, ancak girişi takdir edin!
B00MER

Bunu M2'de yapmanın "en iyi uygulama" yolu olup olmadığından emin değilsiniz, ancak çözümünüz Magento 1.x'ten beri her zaman bunu nasıl yaptığımızdır.
thdoan
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.