Magento 2: Produkt-Repositorys, Filtergruppen und "UND"


12

Ich versuche, ein Produkt-Repository zu verwenden, um eine Liste der Produkte abzurufen. Ich möchte basierend auf zwei Filtern, kombiniert mit einem ANDKriterium, holen , aber die Dinge scheinen nicht zu funktionieren. Verstehe ich nicht, wie Filtergruppen funktionieren? Oder ist dies ein Fehler, der gemeldet werden sollte?

Insbesondere (der Einfachheit halber ein albernes Beispiel) habe ich einen Konstruktor, in den ich einen Filterbuilder, einen Filtergruppenbuilder und einen Suchkriterienbuilder einfüge

public function __construct(
    \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
    \Magento\Framework\Api\FilterBuilder $filterBuilder,
    \Magento\Framework\Api\Search\FilterGroupBuilder $filterGroupBuilder 
)
{
    $this->searchCriteriaBuilder = $searchCriteriaBuilder;
    $this->filterBuilder         = $filterBuilder;
    $this->filterGroupBuilder    = $filterGroupBuilder;
}

Später in einer Methode verwende ich dann die Filterbuilder, um zwei Filter zu erstellen

    $filter1 = $this->filterBuilder->setField('sku')
            ->setValue('24-MB01')
            ->setConditionType('eq')
            ->create();

    $filter2 = $this->filterBuilder->setField('sku')
            ->setValue('WT08-XS-Black')
            ->setConditionType('eq')
            ->create();

Anschließend benutze ich den Builder für Filtergruppe, um eine Filtergruppe zu erstellen, die aus diesen beiden Filtern besteht

    $filter_group = $this->filterGroupBuilder
        ->addFilter($filter1)
        ->addFilter($filter2)
        ->create();

Dann habe ich einen Builder für Suchkriterien verwendet und die Filtergruppe darauf festgelegt

    $criteria = $this->searchCriteriaBuilder
        ->setFilterGroups([$filter_group])
        ->setPageSize(100)
        ->create();            
    return $criteria

Schließlich, wenn ich dieses Kriterium mit einem Produkt-Repository verwende (anderswo verwendet, Konstruktor und di weglassen, um Verwirrung zu vermeiden)

/* @var Magento\Catalog\Api\ProductRepositoryInterface */
$list = $productRepository->getList($searchCriteria);  

Der Anruf ist erfolgreich, aber ich erhalte zwei Produkte zurück. Das heißt, der SKU-Filter wurde als OR, nicht als angewendet AND. Ich würde erwarten, dass diese Abfrage nichts zurückgibt.

Wenn ich mich in die Magento\Catalog\Api\ProductRepositoryKlasse vertiefe, schaue ich mir die ausgewählte Aussage der Sammlung an

protected function addFilterGroupToCollection(
    \Magento\Framework\Api\Search\FilterGroup $filterGroup,
    Collection $collection
) {
    //...
    if ($fields) {
        $collection->addFieldToFilter($fields);
    }

    //printf lives in my heart forever
    echo($collection->getSelect()->__toString());
    exit;
}               

Ich sehe die Kriterien mit einem OR

SELECT `e`.*, IF(at_status.value_id > 0, at_status.value, at_status_default.value) AS `status`, IF(at_visibility.value_id > 0, at_visibility.value, at_visibility_default.value) AS `visibility` 

FROM `catalog_product_entity` AS `e` 

INNER JOIN `catalog_product_entity_int` AS `at_status_default` ON (`at_status_default`.`entity_id` = `e`.`entity_id`) AND (`at_status_default`.`attribute_id` = '94') AND `at_status_default`.`store_id` = 0 LEFT JOIN `catalog_product_entity_int` AS `at_status` ON (`at_status`.`entity_id` = `e`.`entity_id`) AND (`at_status`.`attribute_id` = '94') AND (`at_status`.`store_id` = 1) 

INNER JOIN `catalog_product_entity_int` AS `at_visibility_default` ON (`at_visibility_default`.`entity_id` = `e`.`entity_id`) AND (`at_visibility_default`.`attribute_id` = '96') AND `at_visibility_default`.`store_id` = 0 LEFT JOIN `catalog_product_entity_int` AS `at_visibility` ON (`at_visibility`.`entity_id` = `e`.`entity_id`) AND (`at_visibility`.`attribute_id` = '96') AND (`at_visibility`.`store_id` = 1)

WHERE ((`e`.`sku` = '24-MB01') OR (`e`.`sku` = 'WT08-XS-Black')) 

Ist das ein Bug? Gibt es eine Möglichkeit (sich nicht nur direkt auf die Produktkollektionen zu verlassen und die Repositories zu vernichten), um diese Funktion zu erfüllen?


2
Ich habe mir diesen Bereich noch nicht persönlich angesehen, aber cyrillschumacher.com/2015/01/02/… könnte nützlich sein.
Alan Kent

Antworten:


15

Tatsächliche Annotation von \Magento\Framework\Api\Search\FilterGroupsays (Klasse phpDoc):

Gruppiert zwei oder mehr Filter mit einem logischen ODER

Dies bedeutet, dass Sie zwei Gruppen mit jeweils einem Filter erstellen müssen.


Danke, dass du das geklärt hast. Man muss einfach alle Abstraktionsebenen in Magento 2 lieben :-P
Giel Berkers

2

In Magento 2 werden alle darin enthaltenen Filter FilterGroupmithilfe des OROperators hinzugefügt . Aber alle FilterGroupwerden mit ANDoperator hinzugefügt . Sie müssen also mehrere FilterGroups wie folgt hinzufügen :

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$searchCriteria = $objectManager->create('\Magento\Framework\Api\SearchCriteria');
$filter = $objectManager->create('\Magento\Framework\Api\Filter');
$filter->setField('category_id');
$filter->setValue(array(1, 2, 3));
$filter->setConditionType('in');

$filterGroup = $objectManager->create('\Magento\Framework\Api\Search\FilterGroup');
$filterGroup->setFilters([$filter]);

$filterEnabled = $objectManager->create('\Magento\Framework\Api\Filter');
$filterEnabled->setField('status');
$filterEnabled->setValue(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED);
$filterEnabled->setConditionType('eq');

$filterGroupEnabled = $objectManager->create('\Magento\Framework\Api\Search\FilterGroup');
$filterGroupEnabled->setFilters([$filterEnabled]);


$searchCriteria->setFilterGroups([$filterGroup, $filterGroupEnabled]);

Weitere Details und logische Kombinationen zu Suchkriterien finden Sie unter Magento-2- Suchkriterien


Das ist falsch. Die Logik wird pro Repository implementiert.
Alan Storm

Hallo @Alan Storm, das ist eine getestete Lösung. Ich habe es für den Standardspeicher in Magento 2.1.0 getestet. Haben Sie eine Rechtfertigung, dies für falsch zu erklären, Sir?
Kamal Singh


@ Alan Storm, das habe ich in meiner Antwort erwähnt. Alle Filtergruppen werden mit dem Operator AND verbunden, und alle Filter in einer Filtergruppe werden mit dem Operator OR gemäß der Magento 2-Suchkriteriendokumentation verbunden. Ich habe erwähnt, dass diese Lösung mit Standardspeicher getestet wird. Was macht diese Antwort nach Ihrem Kommentar falsch, ich habe es nicht verstanden.
Kamal Singh

@KamelSingh Hast du den Fehlerbericht gelesen, den ich verlinkt habe? Unabhängig von ihrem beabsichtigten Verhalten hängt das Verhalten von Filtern und Filtergruppen letztendlich vom Verhalten des Repositorys ab, in dem sie sich befinden.
Alan Storm
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.