Magento 2: repository di prodotti, gruppi di filtri e `AND`


12

Sto cercando di utilizzare un repository di prodotti per recuperare un elenco di prodotti. Voglio recuperare in base a due filtri, combinati con un ANDcriterio, ma le cose non sembrano funzionare. Non capisco come funzionano i gruppi di filtri? O è un bug che dovrebbe essere segnalato?

In particolare, (esempio sciocco per semplicità) ho un costruttore in cui iniettare un builder di filtri, builder di gruppi di filtri e builder di criteri di ricerca

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

Quindi, più avanti in un metodo, utilizzo i costruttori di filtri per creare due filtri

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

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

Quindi utilizzo il generatore di gruppi di filtri per creare un gruppo di filtri composto da questi due filtri

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

Quindi ho usato un generatore di criteri di ricerca, ho impostato il gruppo di filtri su di esso

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

Infine, quando uso questi criteri con un repository di prodotti (usato altrove, tralasciando il costruttore e di per evitare confusione)

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

La chiamata è andata a buon fine ma ho ricevuto due prodotti. cioè il filtro SKU è stato applicato come un OR, non un AND. Mi aspetto che questa query non restituisca nulla.

Se riesco a scavare nella Magento\Catalog\Api\ProductRepositoryclasse e dare un'occhiata allo stato selezionato della raccolta

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

Vedo i criteri aggiunti con un 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')) 

è un insetto? Esiste un modo (a parte affidarsi direttamente alle raccolte di prodotti e abbandonare i repository) per farlo funzionare?


2
Non ho ancora esaminato questa zona personalmente, ma cyrillschumacher.com/2015/01/02/… potrebbe essere utile.
Alan Kent,

Risposte:


15

Annotazione effettiva di \Magento\Framework\Api\Search\FilterGroupdice (classe phpDoc):

Raggruppa due o più filtri utilizzando un OR logico

Significa che devi creare due gruppi con un filtro in ciascuno.


Grazie per averlo chiarito. Devi solo amare tutti gli strati di astrazione in Magento 2 :-P
Giel Berkers,

2

In Magento 2 tutti i filtri nella stessa FilterGroupverranno aggiunti usando l' ORoperatore. Ma tutto FilterGroupsarà aggiunto usando l' ANDoperatore. Quindi dovrai aggiungere più FilterGroups come di seguito:

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

Per ulteriori dettagli e combinazioni logiche sui criteri di ricerca, puoi trovare i criteri di ricerca di Magento-2


Questo non è corretto La logica è implementata su base per Repository.
Alan Storm,

Ciao @Alan Storm, questa è una soluzione testata. L'ho testato per l'archivio predefinito in Magento 2.1.0. Ha qualche giustificazione per dichiararlo sbagliato, signore?
Kamal Singh,


@Alan Storm, è quello che ho menzionato nella mia risposta. Tutti i gruppi di filtri vengono uniti utilizzando l'operatore AND e Tutti i filtri nel singolo gruppo di filtri vengono uniti utilizzando l'operatore OR secondo la documentazione relativa ai criteri di ricerca di Magento 2. Ho menzionato che questa soluzione è stata testata con l'archivio predefinito. Ciò che rende questa risposta sbagliata secondo il tuo commento, non l'ho capito.
Kamal Singh,

@KamelSingh Hai letto la segnalazione di bug che ho collegato? Indipendentemente dal comportamento previsto, il comportamento dei filtri e dei gruppi di filtri dipende in ultima analisi dal comportamento del repository in cui si trovano.
Alan Storm
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.