23

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
    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 :\ – Petar Dzhambazov Nov 20 '15 at 16:29
  • 2
    Actually, something like a list can be found at Magento/Framework/Api/CriteriaInterface.php:79 – Petar Dzhambazov Nov 20 '15 at 16:37
28

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
    Thanks, just what I was after! It looks like adding multiple filters creates "OR" conditions — is there a way to create "AND" conditions? – Alan Storm Nov 20 '15 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/… – Alan Storm Nov 20 '15 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[]) – Alex Paliarush Nov 21 '15 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 Feb 10 at 19:49
11
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();
}
  • 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. – Alex Paliarush Nov 20 '15 at 16:50
  • Agreed, it's a slightly different solution. – LDusan Nov 20 '15 at 16:52
  • can addfilter use only 1 param? – Antonio Pedicini Sep 24 '17 at 21:11
  • @LDusan, Can you please tell me how can i use "$searchCriteriaBuilder," in objectmanager ? – Sarfaraj Sipai Oct 16 '17 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 Oct 21 '17 at 19:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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