Magento – Get Product Collection with In-Stock Products Only

ce-1.8.1.0collection-filteringproduct-collection

There may be a simple answer to this, but I can't find it. I'm trying to retrieve a product collection, excluding products that are enabled, but out of stock.

I've tried the following approach, but this kicks out an error:

$productIds = array('3','4','9');

$productCollection = Mage::getResourceModel('catalog/product_collection')
    ->addAttributeToSelect(
        array('name', 'image', 'price')
    )
    ->addIdFilter($productIds)
;

$this->_productCollection = Mage::getSingleton('cataloginventory/stock')
    ->addInStockFilterToCollection( $productCollection )
;

The following error occurs:

PHP Fatal error: Call to a member function getTypeInstance() on a non-object in app/code/core/Mage/Catalog/Block/Product/Abstract.php on line 117

app/code/core/Mage/Catalog/Block/Product/Abstract.php:117 has the following method:

/**
 * Retrieve url for add product to cart
 * Will return product view page URL if product has required options
 *
 * @param Mage_Catalog_Model_Product $product
 * @param array $additional
 * @return string
 */
public function getAddToCartUrl($product, $additional = array())
{
    // line 117:
    if (!$product->getTypeInstance(true)->hasRequiredOptions($product)) {
        return $this->helper('checkout/cart')->getAddUrl($product, $additional);
    }
    $additional = array_merge(
        $additional,
        array(Mage_Core_Model_Url::FORM_KEY => $this->_getSingletonModel('core/session')->getFormKey())
    );
    if (!isset($additional['_escape'])) {
        $additional['_escape'] = true;
    }
    if (!isset($additional['_query'])) {
        $additional['_query'] = array();
    }
    $additional['_query']['options'] = 'cart';
    return $this->getProductUrl($product, $additional);
}

Is there a simple way to filter a collection to get only products that are in stock? Obviously I know about isSaleable() inside the loop. Thanks.

Best Answer

To answer the question. You would use this (not very different than your version):

$productCollection = Mage::getResourceModel('catalog/product_collection')
                        ->addAttributeToSelect(array('name', 'image', 'price'))
                        ->addAttributeToFilter('status', array('eq' => Mage_Catalog_Model_Product_Status::STATUS_ENABLED));

Mage::getSingleton('cataloginventory/stock')
    ->addInStockFilterToCollection($productCollection);

$this->_productCollection = $productCollection;

But I don't know exactly what causes your error, because it seems related to the fact that the getSubmitUrl/getAddToCartUrl product param is boolean false, and not to the collection per se.