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.


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.


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

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)


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()


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


Nie chcę atrybutu w filtrze interfejsu użytkownika - po prostu chcę przeprowadzić filtrowanie kolekcji do użytku wewnętrznego.
— Alex
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.