I'm using magento v2.4.1 and I'm extending \Magento\Catalog\Block\Product\ListProduct in my custom module block to load a custom product collection like this:

protected function _getProductCollection()
    if ($this->_productCollection === null) {
     // \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory 
     $collection = $this->_productCollectionFactory->create()->addAttributeToSelect('*');
     $collection->setFlag('has_stock_status_filter', true);
     $categoryId = $this->getCategoryId();
     $categoryProductTable = $collection->getResource()->getTable('catalog_category_product');
     $collection->getSelect()->where('e.entity_id IN (SELECT product_id FROM '.$categoryProductTable.' WHERE category_id = '.$categoryId.')');
     $collection->addAttributeToFilter('visibility', array(
      \Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE ,
      \Magento\Catalog\Model\Product\Visibility::VISIBILITY_IN_CATALOG ,
      \Magento\Catalog\Model\Product\Visibility::VISIBILITY_IN_SEARCH ,
      \Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH ,
   return $this->_productCollection;

I need to print if the product is saleable or not in .phtml, so i tried to do it like this:

foreach($productCollection as $product){
  echo $product->isSaleable() ? 'Saleable' : 'Not Saleable';

the above code always print Saleable, even though some of the product is not saleable, but if i load the product by id, it will print correctly:

// i add this in block function
public function getProductById($productId){
  return $this->productFactory->create()->load($productId);

// in .phtml i call it like this
foreach($productCollection as $product){
  $product = $this->getProductById($product->getId());
  echo $product->isSaleable() ? 'Saleable' : 'Not Saleable';

I'm trying to avoid to use this load product by id, because it might take a lot of mysql connection if i load huge amount of product collection, how can i achieve to load a product collection along with is saleable functionality ??

1 Answer 1


You can filter the collection to get only products in stock with the flag for has_stock_status_filter:

$collection = $this->_categoryFactory->create()->load($categoryId)
                ->setFlag('has_stock_status_filter', true);

And, there is option


You can use it as your requirements.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.