Magento 2: référentiels de produits, groupes de filtres et «ET»

12

J'essaie d'utiliser un référentiel de produits pour récupérer une liste de produits. Je veux récupérer en fonction de deux filtres, combinés à un ANDcritère, mais les choses ne semblent pas fonctionner. Est-ce que je ne comprends pas comment fonctionnent les groupes de filtres? Ou est-ce un bug qui devrait être signalé?

Plus précisément, (exemple stupide pour des raisons de simplicité), j'ai un constructeur où j'injecte un générateur de filtre, un générateur de groupe de filtres et un générateur de critères de recherche

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

Ensuite, plus tard dans une méthode, j'utilise les constructeurs de filtres pour construire deux filtres

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

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

Ensuite, j'utilise le générateur de groupe de filtres pour créer un groupe de filtres composé de ces deux filtres

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

Ensuite, j'ai utilisé un générateur de critères de recherche, définissez le groupe de filtres dessus

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

Enfin, lorsque j'utilise ce critère avec un référentiel produit (utilisé ailleurs, en laissant de côté constructeur et di pour éviter toute confusion)

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

L'appel est réussi mais je récupère deux produits. c'est-à-dire que le filtre SKU a été appliqué comme un OR, pas comme un AND. Je m'attendrais à ce que cette requête ne renvoie rien.

Si je fouille dans la Magento\Catalog\Api\ProductRepositoryclasse et jette un œil à la sélection de la collection

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

Je vois les critères ajoutés avec 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')) 

Est-ce un bug? Existe-t-il un moyen (à moins de s'appuyer directement sur les collections de produits et d'abandonner les référentiels) pour que cela fonctionne?

Alan Storm
la source
2
Je n'ai pas encore étudié personnellement ce domaine, mais cyrillschumacher.com/2015/01/02/… pourrait être utile.
Alan Kent

Réponses:

15

Annotation réelle de \Magento\Framework\Api\Search\FilterGroupsaid (classe phpDoc):

Regroupe deux filtres ou plus à l'aide d'un OU logique

Cela signifie que vous devez créer deux groupes avec un filtre dans chacun.

Alex Paliarush
la source
Merci d'avoir clarifié cela. Vous devez juste aimer toutes les couches d'abstraction dans Magento 2 :-P
Giel Berkers
2

Dans Magento 2, tous les filtres FilterGroupseront ajoutés à l'aide de l' ORopérateur. Mais tout le FilterGroupsera ajouté à l'aide de l' ANDopérateur. Vous devrez donc ajouter plusieurs FilterGroups comme ci-dessous:

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

Pour plus de détails et des combinaisons logiques sur les critères de recherche, vous pouvez trouver sur Magento-2 Search Criteria

Kamal Singh
la source
Ceci est une erreur. La logique est implémentée par référentiel.
Alan Storm
Salut @Alan Storm, c'est une solution testée. Je l'ai testé pour le magasin par défaut dans Magento 2.1.0. Avez-vous une justification pour le déclarer faux, monsieur?
Kamal Singh
@karnalsingh Ce bug: github.com/magento/magento2/issues/4287
Alan Storm
@Alan Storm, c'est ce que j'ai mentionné dans ma réponse. Tous les groupes de filtres sont joints à l'aide de l'opérateur AND et tous les filtres d'un seul groupe de filtres sont joints à l'aide de l'opérateur OR selon la documentation des critères de recherche de Magento 2. J'ai mentionné que cette solution est testée avec le magasin par défaut. Ce qui rend cette réponse fausse selon votre commentaire, je ne l'ai pas obtenue.
Kamal Singh
@KamelSingh Avez-vous lu le rapport de bug que j'ai lié? Quel que soit leur comportement prévu, le comportement des filtres et des groupes de filtres dépend en fin de compte du comportement du référentiel dans lequel ils se trouvent.
Alan Storm