Reputation: 121
I would like to display the quantity of product on category pages. I have tried the stockRegistry
and it works just fine. However, when it runs on the production environment, for a category with a large number of products, it makes error 500 or other errors which describe does not have the response from the server. I believe the reason is the stockRegistry
created too many requests that cause the problem.
My code is below:
class ListProduct extends \Magento\Catalog\Block\Product\ListProduct {
private $_stockRegistry;
private $stockHelper;
public function __construct(
\Magento\Catalog\Block\Product\Context $context,
\Magento\Framework\Data\Helper\PostHelper $postDataHelper,
\Magento\Catalog\Model\Layer\Resolver $layerResolver,
CategoryRepositoryInterface $categoryRepository,
\Magento\Framework\Url\Helper\Data $urlHelper,
\Magento\CatalogInventory\Api\StockRegistryInterface
$stockRegistry,
Stock $stockHelper,
array $data = []
)
{
$this->_stockRegistry = $stockRegistry;
$this->stockHelper = $stockHelper;
parent::__construct(
$context,
$postDataHelper,
$layerResolver,
$categoryRepository,
$urlHelper,
$data
);
}
public function getProductStock($id) {
return $this->_stockRegistry->getStockItem($id)->getQty();
}
}
And of course, I have updated my XML file to use this class instead.
What would be the way to get the quantity to display on category pages with a better performance?
Upvotes: 1
Views: 1737
Reputation: 339
The correct way to do this is to get quantities for all products on the page
namespace Example\CatalogInventory\Model\ResourceModel;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
class Stock extends AbstractDb
{
/**
* {@inheritdoc}
*/
protected function _construct()
{
$this->_init('cataloginventory_stock_item', 'item_id');
}
/**
* Retrieve products quantities
* Return array as key product id, value - qty
*/
public function getProductsStockQty($productIds, $websiteId, $stockId = \Magento\CatalogInventory\Model\Stock::DEFAULT_STOCK_ID)
{
$select = $this->getConnection()->select()
->from($this->getMainTable(), ['product_id', 'qty'])
->where('product_id IN(?)', $productIds)
->where('stock_id=?', (int)$stockId)
->where('website_id=?', (int)$websiteId);
return $this->getConnection()->fetchPairs($select);
}
}
And use it in your custom block:
class ListProduct extends \Magento\Catalog\Block\Product\ListProduct
{
/**
* @var \Example\CatalogInventory\Model\ResourceModel\Stock
*/
private $stock;
/**
* @var array
*/
private $quantities;
public function __construct(
\Magento\Catalog\Block\Product\Context $context,
\Magento\Framework\Data\Helper\PostHelper $postDataHelper,
\Magento\Catalog\Model\Layer\Resolver $layerResolver,
\Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository,
\Magento\Framework\Url\Helper\Data $urlHelper,
\Example\CatalogInventory\Model\ResourceModel\Stock $stock,
array $data = []
) {
parent::__construct($context, $postDataHelper, $layerResolver, $categoryRepository, $urlHelper, $data);
$this->stock = $stock;
}
public function getProductStock($productId)
{
if (!$this->quantities) {
$this->quantities = $this->stock->getProductsStockQty(
$this->getLoadedProductCollection()->getLoadedIds(),
$this->_storeManager->getStore()->getWebsiteId()
);
}
return $this->quantities[$productId] ?? 0;
}
}
Upvotes: 1