Holen Sie sich die Produktkollektion, die nur vorrätige Produkte enthält

7

Es mag eine einfache Antwort darauf geben, aber ich kann sie nicht finden. Ich versuche, eine Produktkollektion abzurufen, ausgenommen Produkte, die aktiviert, aber nicht vorrätig sind.

Ich habe den folgenden Ansatz ausprobiert, aber dies führt zu einem Fehler:

$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 )
;

Der folgende Fehler tritt auf:

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 / Katalog / Block / Produkt / Abstract.php: 117 hat die folgende Methode:

/**
 * 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);
}

Gibt es eine einfache Möglichkeit, eine Sammlung zu filtern, um nur Produkte zu erhalten, die auf Lager sind? Offensichtlich weiß ich über isSaleable()innerhalb der Schleife Bescheid . Vielen Dank.

Jongosi
quelle
1
Sie zitieren die falsche Methode, beheben ...
Melvyn
1
Und dem nach zu urteilen, geht dies in Ihrer Vorlage schief, nicht in dem Code, den Sie eingefügt haben. Wie durchlaufen Sie Ihre Sammlung und sind Sie sicher, dass der Aufruf in Ihrer Schleife fehlschlägt ? Nicht irgendein Streuner $this->getAddToCartUrl($product)außerhalb davon.
Melvyn

Antworten:

23

Um die Frage zu beantworten. Sie würden dies verwenden (nicht sehr verschieden von Ihrer 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;

Aber ich weiß nicht genau, was Ihren Fehler verursacht, da er mit der Tatsache zusammenhängt, dass der Parameter getSubmitUrl/ getAddToCartUrlproduct boolean false ist und nicht mit der Sammlung an sich.

nieverstand
quelle
Ja, dies ist die Antwort auf die ursprüngliche Frage, thx newermind.
Jongosi
3
Ich befürchte, dass dies für konfigurierbare Produkte nicht hilfreich ist, da es mithilfe der konfigurierbaren Produktbestandsinformationen zu cataloginventory_stock_item beitritt. Dies ist falsch, wenn man bedenkt, dass Magento einfache Produkte verwendet, um zu sagen, ob es verfügbar ist oder nicht.
Ricardo Martins
Großartig, dass mein Problem gelöst wird
Sourav
3

Vielleicht einen Tag zu spät und einen Dollar zu kurz, aber anstatt all diese Arbeit im zweiten Schritt zu erledigen, können Sie einfach die cataloginventorystock_stock_statusTabelle mit Ihrer Sammlung verbinden. Select ():

$collection = Mage::getModel('catalog/product')->getCollection();
$collection->getSelect()->join('cataloginventory_stock_status', 'cataloginventory_stock_status.product_id = e.entity_id', array('stock_status'));
$collection->getSelect()->where("`cataloginventory_stock_status`.`stock_status` = 1");

Sie können dies in Verbindung mit zusätzlichen join () - oder where () -Klauseln tun. Hoffe es hilft dir in die richtige Richtung.

Toby Crain
quelle
2

Newermind beantwortete die ursprüngliche Frage richtig; Mein Dank geht an ihn. Für zukünftige Abenteurer ist hier, was mit meinem Code falsch war. Besonderer Dank geht an Melvyn für seine Hilfe.

Problem

$this->_productCollectionEnthält aus meinem Code in der Frage ein Objekt . Wenn wir dieses Objekt in der Ansicht durchlaufen, ist die $_productVariable ein Array .

$_products = $this->_productCollection;

foreach ( $_products as $_product ) {
    echo gettype( $_product ); // <-- returns type [array]
}

Die Methode bei app/code/core/Mage/Catalog/Block/Product/Abstract.php:117(letztendlich) ruft auf getTypeInstance(). Diese Methode erwartet ein Objekt , insbesondere eine Instanz von Mage_Catalog_Model_Product.

In der Ansicht habe ich $this->getSubmitUrl($_product)innerhalb der foreach-Schleife aufgerufen:

$_products = $this->_productCollection;

foreach ( $_products as $_product ) {
    echo $this->getSubmitUrl( $_product );
}

getSubmitUrl()ist eine Methode von Mage_Catalog_Block_Product_AbstractZeile 115. In Zeile 123 wird aufgerufen getAddToCartUrl(), welche Aufrufe getTypeInstance()und das erwartet ein Objekt . Das Problem war, ich gab ihm ein Array .

Einfaches OOP-Prinzip, aber ich glaube, ich war zu müde, um es zu sehen. Vielen Dank für die Hilfe.

Die Lösung

Leider gibt die addInStockFilterToCollectionMethode ein Inventarobjekt zurück - nicht das, wonach ich gesucht habe. Ich brauche eine Produktsammlung von in-Lager Produkten.

Außerdem addInStockFilterToCollectionfunktioniert die Methode nur mit einer Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Link_Product_CollectionSammlung.

Also, wie bekommt man die Sammlung? Mein Ansatz war wie folgt:

  1. Holen Sie sich eine Sammlung von Lagerprodukten.
  2. Erstellen Sie ein ID-Array aus der Ergebnismenge.
  3. Holen Sie sich die Produktkollektion anhand der IDs aus den Lagerergebnissen.

Hier ist der Code:

$inStockProductIds = array();

$inStockCollection = Mage::getModel('cataloginventory/stock')
    ->getItemCollection()
    ->addFieldToFilter('is_in_stock', 
        array( 'eq' => 1 )
    )
    ->addFieldToFilter( 'entity_id', 
        array( 'in' => array ('1', '2') )
    )
;

if ( $inStockCollection) {
    foreach ($inStockCollection as $stockProduct) {
        $inStockProductIds[] = $stockProduct->getId();
    }
}

$this->_productCollection = Mage::getModel('catalog/product')
    ->getCollection()
    ->addAttributeToSelect(
        array('name', 'image', 'price')
    )
    ->addIdFilter( $inStockProductIds )
    ->setPageSize( 2 )
    ->load();
;

return $this->_productCollection;

Das gibt eine Produktkollektion zurück, die nur vorrätige Produkte enthält. Es ist ein bisschen schwer, aber es funktioniert. Ich würde mich über Verbesserungen freuen. Vielen Dank.

Jongosi
quelle
Warum nicht einfach so etwas machen wie: $collection = Mage::getModel("catalog/product")->getCollection() ... ; Mage::getSingleton('cataloginventory/stock')->addInStockFilterToCollection($col);Beachten Sie, dass ich nichts mit dem Rückgabewert mache, aber die Sammlung wird aktualisiert, um Instock-Filter darauf zu haben.
sbditto85