29

In Magento 2, can you use a product repository to filter by product attributes?

In Magento 2, you can use a search criteria object

\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria,

and a repository

\Magento\Catalog\Api\ProductRepositoryInterface $productRepository,

To fetch a list of objects

$searchCriteria->getPageSize(10);
$list = $productRepository->getList($searchCriteria);

However, the searchCriteria object doesn't (seem to?) have direct filtering capabilities. The search criteria class does have methods for adding something called filterGroups

#File: lib/internal/Magento/Framework/Api/SearchCriteria.php        

public function getFilterGroups()
{
    $filterGroups = $this->_get(self::FILTER_GROUPS);
    return is_array($filterGroups) ? $filterGroups : [];
}

public function setFilterGroups(array $filterGroups = null)
{
    return $this->setData(self::FILTER_GROUPS, $filterGroups);
}    

But it's not clear what, exactly, a filter group is thanks to PHP's untyped arrays.

How can I use a Magento 2 repository to do things like

  • Show me all the products with [this specific SKU]
  • Show me all the products created after [this date]
  • etc.
2
  • 2
    It seems that said groups is an array of Magento\Framework\Api\Search\FilterGroup , which in turn has \Magento\Framework\Api\Filter filters, filters can be built with \Magento\Framework\Api\FilterBuilder and condition_type is in the form of 'eq', 'neq', 'gt' etc. But couldn't find list of supported condition types :\ Commented Nov 20, 2015 at 16:29
  • 2
    Actually, something like a list can be found at Magento/Framework/Api/CriteriaInterface.php:79 Commented Nov 20, 2015 at 16:37

2 Answers 2

40

Check out the following sample class. To filter by SKU, try this:

$productFilterDemo->getProducts('sku', 'product_sku_value', 'eq');

To get products created after specific date, this:

$productFilterDemo->getProducts('created_at', 'creation date', 'gt');

Sample class:

<?php
namespace Vendor\ModlueName\Model;

use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Catalog\Api\ProductRepositoryInterface;

class ProductFilterDemo
{
    /** @var ProductRepositoryInterface */
    protected $productRepository;

    /** @var SearchCriteriaBuilder */
    protected $searchCriteriaBuilder;

    /**
     * Initialize dependencies.
     *
     * @param ProductRepositoryInterface $productRepository
     * @param SearchCriteriaBuilder $searchCriteriaBuilder
     */
    public function __construct(
        ProductRepositoryInterface $productRepository,
        SearchCriteriaBuilder $searchCriteriaBuilder
    ) {
        $this->productRepository = $productRepository;
        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
    }

    /**
     * Get products with filter.
     * 
     * @param string $fieldName
     * @param string $fieldValue
     * @param string $filterType
     * @return \Magento\Catalog\Api\Data\ProductInterface[]
     */
    public function getProducts($fieldName, $fieldValue, $filterType)
    {
        $searchCriteria = $this->searchCriteriaBuilder->addFilter($fieldName, $fieldValue, $filterType)->create();
        $products = $this->productRepository->getList($searchCriteria);
        return $products->getItems();
    }
}
4
  • 4
    Thanks, just what I was after! It looks like adding multiple filters creates "OR" conditions — is there a way to create "AND" conditions? Commented Nov 20, 2015 at 17:08
  • 3
    — if you have a moment. Am I using filter group correctly? They seem to be applying as an OR, not an AND magento.stackexchange.com/questions/91023/… Commented Nov 20, 2015 at 23:35
  • 4
    Filters are combined with "OR" inside one filter group, and each group is combined with "AND" on level of search criteria. Take a look at: \Magento\Framework\Api\SearchCriteriaBuilder::setFilterGroups($groups[]) and \Magento\Framework\Api\Search\FilterGroupBuilder::setFilters($filters[]) Commented Nov 21, 2015 at 0:04
  • I am using Magento 2.3, Search criteria builder does not filter the item if an item is "out_of_stock"?
    – Octopus
    Commented Feb 10, 2019 at 19:49
17
public function __construct(
    ProductRepositoryInterface $productRepository,
    SearchCriteriaBuilder $searchCriteriaBuilder,
    FilterBuilder $filterBuilder,
) {
    $this->productRepository = $productRepository;
    $this->searchCriteriaBuilder = $searchCriteriaBuilder;
    $this->filterBuilder = $filterBuilder;
}

public function getProducts()
{
    $filters[] = $this->filterBuilder
        ->setField('sku')
        ->setConditionType('eq')
        ->setValue('something')
        ->create();
    $this->searchCriteriaBuilder->addFilters($filters);

    $searchCriteria = $this->searchCriteriaBuilder->create();
    $searchResults = $this->productRepository->getList($searchCriteria);
    return $searchResults->getItems();
}
5
  • 1
    Looks like in your example \Magento\Framework\Api\Search\SearchCriteriaBuilder is used (search-specific one), while I used \Magento\Framework\Api\SearchCriteriaBuilder (generic for all services), see my answer. Also it provides simpler way of adding filter, addFilter() signatures are different. Commented Nov 20, 2015 at 16:50
  • Agreed, it's a slightly different solution.
    – LDusan
    Commented Nov 20, 2015 at 16:52
  • can addfilter use only 1 param?
    – apedic
    Commented Sep 24, 2017 at 21:11
  • @LDusan, Can you please tell me how can i use "$searchCriteriaBuilder," in objectmanager ? Commented Oct 16, 2017 at 14:16
  • 2
    I think that you should add it in the constructor of your class, why would you want to use the object manager for that?
    – LDusan
    Commented Oct 21, 2017 at 19:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.