Filtruj kolekcję produktów według atrybutu niepłaskiego

14

Wykonuję następujące czynności:

$productCollection = Mage::getModel('catalog/product')
    ->getCollection();

$productCollection
    ->addAttributeToFilter('my_attribute', 1);

my_attribute nie ma w płaskich tabelach, ale płaskie stoliki są włączone.

Cały czas otrzymuję pełną kolekcję.

Przyczyną wydaje się być \Mage_Catalog_Model_Resource_Product_Collection::addAttributeToSelect:

$columns = $this->getEntity()->getAttributeForSelect($attributeCode);

Nie $this->getEntity()jest instancją, Mage_Catalog_Model_Resource_Product_Flatktóra pobiera płaskie pola - a jeśli nie zostanie znaleziona, po prostu zwraca null.

Jaki jest czysty sposób na dodanie niepłaskiego atrybutu do filtra kolekcji?

W moim przypadku nie ma sensu dodawanie atrybutu do płaskiego stołu.

Alex
źródło
Cześć, proszę pana. Czy jesteś W porządku, aby rozwiązać zamieszanie? WAT oznacza non-flat attribute? Dzięki. I nie wprowadzaj w błąd Magento. To już jest mylące
Pratik
Mówię o atrybutach, których nie ma w indeksie płaskim. Są to te, dla których „Używany na liście produktów” jest ustawiony na „Nie”.
Alex

Odpowiedzi:

18

Możesz sam dołączyć do niezbędnego stołu.

$productCollection = Mage::getModel('catalog/product')
->getCollection();

$table = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'my_attribute')->getBackend()->getTable();
$attributeId = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'my_attribute')->getAttributeId();

$productCollection->getSelect()->join(array('attributeTable' => $table), 'e.entity_id = attributeTable.entity_id', array('my_attribute' => 'attributeTable.value'))
                            ->where("attributeTable.attribute_id = ?", $attributeId)
                            ->where("attributeTable.value = ?", 1);

Możesz także dołączyć do store_id.

Matthias Zeis
źródło
Myślę, że nadal miałbym problem, że nie otrzymuję produktów ze wszystkich sklepów. (za każdym razem, gdy pierwotnie nie widziałem tego problemu w moim pytaniu). Wygląda na to, że chcę całkowicie wyłączyć indeksy płaskie.
Alex
Jeśli potrzebujesz wszystkich produktów, płaskie stoliki nie będą twoimi przyjaciółmi, tak.
Matthias Zeis,
Myślę, że możesz zmodyfikować swoje pytanie lub zaakceptować moją odpowiedź (która działa w przypadku pierwotnego pytania).
Matthias Zeis
awasome .. koncepcja
Amit Bera
15

Hack (CE 1.6.2.0+) ma na celu przekazanie warunku jako tablicy i uwierzenie, że nie działa to zgodnie z przeznaczeniem:

$collection->addFieldToFilter(array(array('attribute' => 'my_attribute', 'eq' => 1)));
ColinM
źródło
Wszelkie wskazówki, dlaczego to działa?
Alex
3
Działa, ponieważ dla kolekcji eav addFieldToFilerjest to opakowanie addAttributeToFilteri ma ona opcję przekazania atrybutu jako tablicy:if (is_array($attribute)) { $sqlArr = array(); foreach ($attribute as $condition) { $sqlArr[] = $this->_getAttributeConditionSql($condition['attribute'], $condition, $joinType); } $conditionSql = '('.implode(') OR (', $sqlArr).')'; }
Marius
@Marius, czy to oznacza, że ​​to nie hack? : P Czy mogę czuć się dobrze z jego użyciem?
Erfan,
3
@Erfan. to nie hack. to funkcja.
Marius
Słodkie. Nadal dziwne jest, że implementacja tabeli produktów (eav / flat) nie jest oderwana od rzeczy tak prostych, jak filtrowanie kolekcji. Czy to oznacza, że ​​zawsze muszę używać addFieldToFilter zamiast addAttributeToFilter w moim kodzie, ponieważ nie będę wiedział, czy używa eav czy płaskiego? Jaki jest sens addAttributeToFilter?
Erfan
6

Powodem jest odpowiedź ColinM działa to spowodowane kodu w app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php„s addAttributeToFiltermetody. Jeśli użyjesz tego formatu tablicy, nie będzie on wywoływał addAttributeToSelect. W trybie płaskim addAttributeToSelectdyskretnie kończy się niepowodzeniem, jeśli atrybutu nie ma w płaskim stole.

(poniżej znajduje się ponowna analiza mojej odpowiedzi na /programming/6271284/can-i-add-other-attributes-to-magentos-flat-product-catalog-table/17021620 - Jestem nie jestem pewien, do czego służy etykieta, ale wiem, że byłbym pomocny)

Chciałem „czystego” rozwiązania do wybierania kolekcji w trybie płaskim i filtrowania atrybutów niepłaskich, które:

  • nie wymaga, aby atrybut miał określone ustawienia w adminie (może być dodany przez użytkownika lub ukryty w interfejsie użytkownika)
  • działa zarówno w trybie płaskim, jak i innym niż płaski

Użyłem powiązanej kolekcji produktów, ale dotyczy to każdej kolekcji EAV.

Błąd kodu:

$_product = Mage::getModel('catalog/product')->loadByAttribute( 'sku', 'ABC123' );
$coll = $_product->getTypeInstance()->getAssociatedProductCollection()
    ->addAttributeToSelect( 'my_custom_attribute' )
    ->addAttributeToFilter( 'my_custom_attribute', 3 )
;

W trybie płaskim powyższy kod po cichu nie wybiera lub nie filtruje atrybutu, jeśli zdarza się, że nie znajduje się on w płaskiej tabeli.

Dodawanie do wybranych:

$_product = Mage::getModel('catalog/product')->loadByAttribute( 'sku', 'ABC123' );
$coll = $_product->getTypeInstance()->getAssociatedProductCollection()
    ->joinAttribute( 'my_custom_attribute', 'catalog_product/my_custom_attribute', 'entity_id', null, 'left' )
    ->addAttributeToSelect( 'my_custom_attribute' )
;

joinAttributeMetoda dodaje dołączyć do kwerendy dla żądanej konkretnego atrybutu. Nadal działa, gdy atrybut znajduje się już w płaskim stole, ale będzie nieco mniej wydajny niż samo użycie płaskiego stołu.

Użyłem leftsprzężenia, aby upewnić się, że pobiera produkty, jeśli my_custom_attributenie jest ustawiony na tych produktach. Zmień to, innerjeśli interesują Cię tylko wiersze, w których my_custom_attributejest ustawiony.

Dodanie do filtra (zgodnie z ColinM powyżej):

$_product = Mage::getModel('catalog/product')->loadByAttribute( 'sku', 'ABC123' );
$coll = $_product->getTypeInstance()->getAssociatedProductCollection()
    ->addAttributeToFilter( array( array( 'attribute' => 'my_custom_attribute', 'eq' => 3 ) ) )
;

Powyższy kod doda go do zaznaczenia, a także będzie przestrzegał twojego filtra.

(testowany w CE 1.6.2.0)

johnorourke
źródło
4

W Mage_Rssmodule zastosowali metodę hacky do wyłączenia płaskich tabel. Wykorzystują fakt, że płaskie tabele są zawsze wyłączone w sklepie administracyjnym, więc po prostu emulują sklep administracyjny.

class Mage_Rss_Helper_Data {

[...]

/**
 * Disable using of flat catalog and/or product model to prevent limiting results to single store. Probably won't
 * work inside a controller.
 *
 * @return null
 */
public function disableFlat()
{
    /* @var $flatHelper Mage_Catalog_Helper_Product_Flat */
    $flatHelper = Mage::helper('catalog/product_flat');
    if ($flatHelper->isEnabled()) {
        /* @var $emulationModel Mage_Core_Model_App_Emulation */
        $emulationModel = Mage::getModel('core/app_emulation');
        // Emulate admin environment to disable using flat model - otherwise we won't get global stats
        // for all stores
        $emulationModel->startEnvironmentEmulation(0, Mage_Core_Model_App_Area::AREA_ADMINHTML);
    }
}

Po rozpoczęciu emulacji powinieneś ją zresetować emulationModel->stopEnvironmentEmulation()

Alex
źródło
Gdzie była ta odpowiedź 3 dni temu? ; _;
sg3s
Tutaj? Od 20 marca
Alex
1

podczas tworzenia atrybutu powinien on znajdować się na poziomie globalnym i być filtrowalny. W ten sposób będzie można go używać w nawigacji warstwowej. Będzie również wymagał atrybutu rozwijanego lub wielokrotnego wyboru. Osobiście odradzałbym zmianę podstawowych plików w celu dopasowania do twoich potrzeb w tym przypadku

Sander Mangel
źródło
Nie chcę atrybutu w filtrze interfejsu użytkownika - po prostu chcę przeprowadzić filtrowanie kolekcji do użytku wewnętrznego.
Alex