Magento 2: Repositori Produk, Grup Filter, dan `AND`

12

Saya mencoba menggunakan repositori produk untuk mengambil daftar produk. Saya ingin mengambil berdasarkan dua filter, dikombinasikan dengan ANDkriteria, tetapi hal-hal tampaknya tidak berfungsi. Apakah saya tidak mengerti cara kerja grup filter? Atau ini bug yang harus dilaporkan?

Secara khusus, (contoh konyol demi kesederhanaan) Saya memiliki konstruktor di mana saya menyuntikkan pembuat filter, pembuat grup filter, dan pembuat kriteria pencarian

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

Kemudian, nanti dalam suatu metode, saya menggunakan pembuat filter untuk membangun dua filter

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

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

Lalu saya menggunakan pembuat grup filter untuk membangun grup filter yang terdiri dari dua filter ini

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

Lalu saya menggunakan pembuat kriteria pencarian, mengatur grup filter di atasnya

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

Akhirnya, ketika saya menggunakan kriteria ini dengan repositori produk (digunakan di tempat lain, meninggalkan konstruktor dan di untuk menghindari kebingungan)

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

Panggilan berhasil tetapi saya mendapatkan kembali dua produk. yaitu filter SKU diterapkan sebagai OR, bukan AND. Saya berharap permintaan ini tidak menghasilkan apa-apa.

Jika saya menggali Magento\Catalog\Api\ProductRepositorykelas, dan melihat statment pilih koleksi

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

Saya melihat kriteria ditambahkan dengan 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')) 

Apakah ini bug? Apakah ada cara (dengan tidak bergantung langsung pada koleksi produk dan membuang repositori) untuk membuatnya bekerja?

Alan Storm
sumber
2
Saya belum melihat ke daerah ini secara pribadi, tetapi cyrillschumacher.com/2015/01/02/ ... mungkin berguna.
Alan Kent

Jawaban:

15

Anotasi \Magento\Framework\Api\Search\FilterGroupkata aktual (kelas phpDoc):

Grup dua atau lebih filter bersama-sama menggunakan OR logis

Ini berarti bahwa Anda perlu membuat dua grup dengan masing-masing filter.

Alex Paliarush
sumber
Terima kasih telah menjelaskan ini. Anda baru saja menyukai semua lapisan abstraksi di Magento 2 :-P
Giel Berkers
2

Di Magento 2 semua filter yang sama FilterGroupakan ditambahkan menggunakan ORoperator. Namun semua itu FilterGroupakan ditambahkan menggunakan ANDoperator. Jadi, Anda perlu menambahkan beberapa FilterGroups seperti di bawah ini:

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

Dalam perincian lebih lanjut dan kombinasi logis tentang kriteria pencarian, Anda dapat menemukannya di Kriteria Pencarian Magento-2

Kamal Singh
sumber
Ini salah. Logika diimplementasikan berdasarkan per Repositori.
Alan Storm
Hai @Alan Storm, ini adalah solusi teruji. Saya telah mengujinya untuk toko default di Magento 2.1.0. Apakah Anda punya pembenaran untuk menyatakannya salah, Pak?
Kamal Singh
@karnalsingh Bug ini: github.com/magento/magento2/issues/4287
Alan Storm
@Lan Storm, itulah yang saya sebutkan dalam jawaban saya. Semua Grup Filter digabungkan menggunakan operator AND dan Semua Filter dalam Grup Filter tunggal digabungkan menggunakan operator ATAU sesuai dokumentasi kriteria pencarian Magento 2. Saya telah menyebutkan bahwa solusi ini diuji dengan toko default. Apa yang membuat jawaban ini salah sesuai komentar Anda, saya tidak mengerti.
Kamal Singh
@KamelSingh Apakah Anda membaca laporan bug yang saya tautkan? Terlepas dari perilaku yang dimaksudkan, perilaku filter dan grup filter pada akhirnya tergantung pada perilaku repositori mereka.
Alan Storm