ประสิทธิภาพ: เพิ่มระดับสต็อกสินค้าคงคลังในรายการผลิตภัณฑ์ list.phtml ทุกประเภทผลิตภัณฑ์


12

TL; DR , ความต้องการคือการมีระดับสต็อคสินค้าคงคลังที่แสดงในหน้ารายการผลิตภัณฑ์หมวดหมู่ที่มีการสืบค้น / หน่วยความจำเพิ่มเติมเล็กน้อยเพียงเล็กน้อยโดยคำนึงถึงประสิทธิภาพที่สอดคล้องกับกรอบของวีโอไอพี


หลังจากอ่านบทความวินัย Kopp ในการพรีโหลดสำหรับความยืดหยุ่น

วิธีที่ดีที่สุดในการรวมระดับสต็อกสินค้าคงคลังในหน้ารายการผลิตภัณฑ์หมวดหมู่คือ ( list.phtml ) ที่มีการค้นหา / โหลดเพิ่มเติมสำหรับการปฏิบัติงานให้น้อยลง

ฉันรู้วิธีการบางอย่าง:

afterLoad ()ดูเหมือนว่าทำงานได้ดีกับmedia_galleryการรวมโดยไม่มีการค้นหาเพิ่มเติม แต่ฉันไม่ประสบความสำเร็จในการใช้วิธีการเดียวกันกับคลังโฆษณา

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

Direct SQLเพื่อรวบรวมข้อมูลที่ต้องการควบคู่ไปกับการรวบรวมด้วยproduct_idคีย์เช่น แต่มองหาวิธีการเพิ่มเติมผ่านกรอบ

ขณะนี้ฉันกำลังโหลดstock_itemวัตถุผ่าน:

$_product->load('stock_item')->getTotalQty(); ใช้งานได้จริง แต่ฉันสังเกตเห็นว่ามีการเพิ่มข้อความค้นหาเพิ่มเติมเพื่อรับผลรวมสต็อคสินค้าคงคลังของผลิตภัณฑ์ทั้งหมดในคอลเลกชัน

...

__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)

...

แปลกงานนี้ ความมหัศจรรย์เกิดขึ้นใน Mage_Eav_Model_Entity_Abstract-> load ($ object, $ entityId, $ attribute) ถ้า $ attribute นั้นว่างเปล่ามันจะเรียก loadAllAttribute ($ object) ดังนั้น $ product-> load ('blah') จะโหลดแอตทริบิวต์ที่หายไปทั้งหมดรวมถึง 'media_gallery' - William Tran 19 พ.ย. 14 '14 ที่ 4:45

เพิ่มค่าที่ต้องการลงในคอลเล็กชันที่โหลดแล้ว

วิธีง่าย ๆ ที่ชัดเจนของการเพิ่มข้อมูลที่ต้องการลงในคอลเลกชันการผลิตระดับสูงสุดในเลเยอร์ / ตัวกรองดูเหมือนจะเป็นวิธีที่ดีที่สุด

ฉันสังเกตเห็นผู้สังเกตการณ์addInventoryDataToCollection ()ในMage_CatalogInventory_Model_Observerที่ดูเหมือนว่ามันจะบรรลุผลดังกล่าว แต่การเพิ่มวิธีการในโมดูลผู้สังเกตการณ์แบบกำหนดเองนั้นดูเหมือนจะไม่เข้ากัน

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

ซึ่งผลลัพธ์ใน:

คำเตือน: อาร์กิวเมนต์ที่ระบุไม่ถูกต้องสำหรับ foreach () ใน /app/code/core/Mage/CatalogInventory/Model/Resource/Stock/Item/Collection.php ที่บรรทัดที่ 71


1
Good question boomer
Amit Bera

คำตอบ:


4

ปัญหาจริงที่นี่ไม่ได้ทำการโหลดล่วงหน้าความแม่นยำ มันค่อนข้างง่ายที่จะได้รับจำนวนสต็อกสำหรับการรวบรวมผลิตภัณฑ์:

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

ขณะนี้มีสองคำค้นหาคุณมีข้อมูลทั้งหมดที่คุณต้องการ พวกมันแค่ยากที่จะเกี่ยวข้องซึ่งกันและกันซึ่งสามารถแก้ไขได้โดยใช้อาเรย์แบบเชื่อมโยง'product_id' => 'stock'และเขียนตัวทะเยอทะยาน นอกจากนี้ addProductsFilter สามารถปรับให้เหมาะสม:

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

สิ่งนี้จะช่วยคุณประหยัดการตรวจสอบประเภทและการโคลนอาร์เรย์

ปัญหาตอนนี้คือ Block HTML cache หน้าหมวดหมู่นี้จะต้องถูกกำจัดเมื่อมีการอัพเดทสต็อกสินค้าที่มีอยู่ในนั้น เท่าที่ฉันรู้นี่ไม่ได้เป็นมาตรฐานเนื่องจากมีเพียงการเปลี่ยนสถานะหุ้นล้างหน้าหมวดหมู่ที่มีผลิตภัณฑ์ (หรือถูกต้องมากขึ้นการเปลี่ยนแปลงการมองเห็น) ดังนั้นคุณจะต้องสังเกตอย่างน้อยที่สุดcataloginventory_stock_item_before_saveและอาจมีคนอื่นอีกเล็กน้อยและล้างแคชบล็อก html (และแคช FPC) สำหรับหน้าหมวดหมู่นั้น


จุดสุดท้ายของคุณคือเหตุผลที่เราไปขอเพิ่มเติมเพื่อดึงข้อมูลหุ้น หากคุณมีหมวดหมู่ด้วยผลิตภัณฑ์ที่เคลื่อนไหวเร็วแคชคุณจะใช้เวลาส่วนใหญ่ในการล้าง / ตรวจสอบความถูกต้อง ครั้งเดียวที่เราจำเป็นต้องล้างแคชหน้าหมวดหมู่คือถ้าผลิตภัณฑ์ถูกลบออกจากหมวดหมู่นั้น ไม่มีวิธีแก้ปัญหาเวทย์มนตร์อย่างใดอย่างหนึ่งที่คุณต้องใช้เพื่อให้เกิดประสิทธิภาพสูงสุดในแต่ละกรณี หากคุณต้องการคุณสามารถแคชข้อมูลสต็อกได้เท่านั้นที่จะต้องสร้างใหม่หลังจากล้างข้อมูลทั้งหมดแทนที่จะเป็นทั้งหน้า
john-jh

หากคุณใช้ข้อมูลสต็อคด้วยวิธีเดียวกับที่คุณทำตอนนี้โดยใช้ข้อมูล JavaScript เพื่ออัปเดต DOM คุณสามารถเขียนว่าใช้บล็อกด้วยคีย์แคชของตัวเองและทำให้ข้อมูลสต็อคไม่ถูกต้องเท่านั้น นี่คือวิธีที่ฉันจะทำกับสถานการณ์ของคุณและไม่ได้ใช้ FPC ที่ใช้ ESI แต่เป็นสิ่งที่สามารถเจาะรูบล็อกในตัวประมวลผลคำขอ ไม่เพียง แต่สำหรับเราเตอร์บิต แต่ยังต้องการล่าม php เพียงหนึ่งรายการต่อหน้า เมื่อเครื่องตกอยู่ภายใต้แรงกดดันไม่ว่าด้วยเหตุผลใดล่าม php ของคุณเป็นทรัพยากรที่ใช้ CPU มากที่สุด นี้จะเริ่มเสียงมากขึ้นเช่นโครงการวันหยุดสุดสัปดาห์ที่ดี ;-)
เมลวิน

3
นี่คือประเภทของสิ่งที่ทำให้งานน่าสนใจจริง ๆ ที่คุณต้องคิดเกี่ยวกับการใช้งานและปัญหาที่อาจเกิดขึ้นและคอขวด ฉันท้าทายที่จะเห็นว่าคุณมาจากกระบวนการ PHP เดียวในตอนนี้ไม่ใช่ปัญหาสำหรับเรา แต่สามารถดูว่ามันจะส่งผลกระทบอย่างไรเมื่อคุณปรับขนาด มูลค่าสต็อคที่แสดงในหน้านั้นไม่ใช่ฟังก์ชั่นการทำงานที่สำคัญดังนั้นเราจึงโหลดเป็นทรัพยากรรองหลังจากโหลดโดยไม่ส่งผลกระทบต่อผู้ใช้ มันเป็นความอัปยศในรายการผลิตภัณฑ์ไม่ใช่คุณสมบัติเริ่มต้น
john-jh

1
ใช่ฉันกำลังเล่นกับความคิดในขณะนี้เพื่อดึงข้อมูลนี้จาก Redis โดยตรงและตัด php ออก มีบางงานที่น่าสนใจจริงๆนี่โดยอี้ชุนจางบนเปิด Resty
Melvyn

2

ฉันเห็นว่าคุณได้รับการยอมรับแล้วและไม่ต้องสงสัยเลยว่าจะมีการใช้งานบางอย่างในตอนนี้ แต่ฉันอยากจะชี้ให้เห็นว่าคุณอยู่ใกล้แค่ไหนaddInventoryDataToCollection()แต่ดูเหมือนว่าคุณบิดเบือนไฟล์ปรับแต่ง สำเนาของฉันCatalogInventory/etc/config.xmlมีวิธีที่แตกต่างที่เรียกว่าcatalog_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() เรียกว่า <sales_quote_item_collection_products_after_load>

แหล่งที่มาสำหรับ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_itemsในคอลเลกชันก่อนที่จะโหลดอาจไม่ใช่เรื่องง่ายสำหรับบล็อกที่อยู่เบื้องหลังรายการหมวดหมู่หรือคุณสามารถโทร Mage::getModel('cataloginventory/stock')->addItemsToProducts($productCollection)ด้วยตนเองในคอลเล็กชันหลังจากโหลดเสร็จแล้ว addItemsToProducts()รับ StockItems ทั้งหมดให้คุณและแนบไปกับ ProductCollection ของคุณ

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

คุณใช้น้ำยาวานิชหรือ FPC หรือวางแผนที่จะใช้ในอนาคตหรือไม่?

เราพบว่ามีจำนวนการเจาะรู / คำขอ ESI ที่ต้องการในรายชื่อผลิตภัณฑ์ซึ่งแทบจะไม่คุ้มค่าหากมีการแคชในสถานที่ดังนั้นจึงเลือกใช้วิธีอื่น

เรานำวิธีการแก้ปัญหาในเว็บไซต์หนึ่งที่ใช้การร้องขอ AJAX ไปยังตัวควบคุมที่กำหนดเองเพื่อดึงข้อมูลหุ้นสำหรับผลิตภัณฑ์และจาวาสคริปต์จัดการการปรับปรุง DOM คำขอเพิ่มเติมสำหรับข้อมูลสต็อคใช้เวลาประมาณ ~ 100ms ซึ่งไม่ส่งผลกระทบต่อความเร็วในการโหลดหน้าเว็บโดยรวม (มองเห็นได้) เลย คู่กับ FPC ที่ทำสีพื้นหน้าวางคำขอลงไปต่ำกว่า 100ms คุณมีเว็บไซต์รวดเร็วที่มีค่าใช้จ่ายประสิทธิภาพต่ำสำหรับการแสดงข้อมูลหุ้นในรายการผลิตภัณฑ์

สิ่งที่คุณต้องทำคือสร้างเทมเพลตที่ชาญฉลาดคือเพิ่ม productId ให้กับแต่ละ wrapper html เพื่อให้จาวาสคริปต์ของคุณรู้ว่าข้อมูลสต็อคใดที่จะนำไปใช้กับแต่ละผลิตภัณฑ์

หากคุณดูเทคนิคการแคชเพิ่มเติมสำหรับข้อมูลหุ้นจริงคุณสามารถปล่อยให้ต่ำกว่า 100ms ได้โดยไม่ต้องเริ่ม Mage / กดฐานข้อมูลในแต่ละคำขอ

ขออภัยหากไม่ตรงกับสิ่งที่คุณกำลังมองหา แต่เราพบว่ามันเป็นวิธีที่ดีที่สุดในการปรับขนาดและประสิทธิภาพตามความต้องการของเรา


2
ปรับใช้ความโกลาหลลิงและดูว่าเกิดอะไรขึ้นเมื่อที่เก็บแคชของคุณล้มเหลว คำถามนี้กล่าวถึงโดยเฉพาะว่าไม่ต้องพึ่งพาแคช มันเป็นคำตอบเช่นนี้ที่ทำให้งานของเราโน้มน้าวใจลูกค้าว่า FPC จะไม่แก้ไขเทมเพลต BuiltIn / MomsBasement ของพวกเขาให้หนักยิ่งขึ้น
Melvyn

คุณเข้าใจผิดจริง ๆ คำตอบของฉันถ้าคุณคิดว่าฉันแนะนำ FPC / Varnish สำหรับประสิทธิภาพและเป็นวิธีแก้ปัญหา ฉันระบุว่าพวกเขากำลังใช้หรือกำลังพิจารณา FPC / Vanish พวกเขาควรตรวจสอบวิธีการนี้เพื่อลดการเจาะรู / การร้องขอ ESI เราได้รับข้อมูลสต็อคที่เราต้องการภายใน 100ms โดยไม่มี leaveraging cache
john-jh

และคุณจะได้รับข้อมูลเดียวกันในเวลาเดียวกันโดยใช้ ESI วิธีการของคุณกับ ESI นั้นแตกต่างกันอย่างสิ้นเชิง ดังนั้นโดยไม่มีแคชคุณยังสามารถรับข้อมูลเดียวกันได้ในเวลาน้อยลง แทนที่จะต้องผ่านเราเตอร์ตัวอื่นเพื่อส่ง JSON กลับมาคุณเขียนอาร์เรย์หุ้นใน JavaScript ที่อัปเดต DOM และอื่น ๆ ใส่ใน JSON ถ้าคุณต้องการเพียงตัดเราเตอร์ออก
Melvyn

1
การแคชจะถูกนำไปใช้ แต่คำถามนั้นมีมากขึ้นตามแนวของการปรับปรุงประสิทธิภาพ พื้นหลังบางส่วน: magento.stackexchange.com/questions/13957/… (ไม่มีแคช / แทบจะไม่ใด ๆ ) ขอบคุณสำหรับการตอบกลับ แต่ขอบคุณการป้อนข้อมูล!
B00MER

ไม่แน่ใจว่ามีวิธี "ปฏิบัติที่ดีที่สุด" ในการทำสิ่งนี้ใน M2 หรือไม่ แต่วิธีการแก้ปัญหาของคุณคือวิธีที่เราทำมาตั้งแต่ Magento 1.x
thdoan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.