5

I have a variable which containing value to filter both name or sku, i tried to filter the product collection using this variable like this:

$queryName = 'bat';
$category = $this->_categoryFactory->create()->load('2');
$collection = $this->_productCollectionFactory->create();
$collection->addAttributeToSelect('*');
$collection->addCategoryFilter($category);
$collection->addAttributeToFilter(['name', 'sku'],
          [
           ['like' => '%'.$queryName.'%'],
           ['like' => '%'.$queryName.'%']
          ]);
$collection->setPage(1,15)->load();
return $collection;

but i got an error like this:

Warning: Illegal string offset 'attribute' in /../vendor/magento/module-eav/Model/Entity/Collection/AbstractCollection.php on line 362

2
  • changes $collection->addAttributeToFilter(['name', 'sku'], [ ['like' => '%'.$queryName.'%'], ['like' => '%'.$queryName.'%'] ]); to $collection->addAttributeToFilter('name', [ ['like' => '%'.$queryName.'%'], ['like' => '%'.$queryName.'%'] ]) ->addAttributeToFilter('sku', [ ['like' => '%'.$queryName.'%'], ['like' => '%'.$queryName.'%'] ];
    – Amit Bera
    Commented Oct 24, 2017 at 7:33
  • @AmitBera It will product AND filter between sku and name not OR Commented Oct 24, 2017 at 8:45

1 Answer 1

7

The syntax for addAttributeToFilter() that you are using was possible in Magento 1, but in Magento 2 there is only one way to use the method to add multiple filters with OR, namely with a single argument:

$collection->addAttributeToFilter(
      [
       ['attribute' => 'name', 'like' => '%'.$queryName.'%'],
       ['attribute' => 'sku', 'like' => '%'.$queryName.'%']
      ]);

That's why you get this error message: Magento expects an array, where you pass 'name' and 'sku'. And while you can use square brackets to access characters in a string ('name'[0]), a non-numeric index as in 'name'['attribute'] throws an error.


Service contracts

You might wonder, if you can achieve the same using the product repository instead of collections, which is the recommended and more upgrade safe way. Repositories are part of the @api service contract of each module and are treated carefully regarding backwards compatibility, while collections are an implementation detail which will not stay the same in the long run.

If it's possible to achieve what you need with repositories, you should do it (see: When Should We Use a Repository and Factory in Magento 2?))

In this case, it's too complicated and imperformant (as of ):

  • There's Magento\Catalog\Api\CategoryLinkManagementInterface::getAssignedProducts() to retrieve a sorted list of SKUs for a given category id, but it does not accept additional filters
  • You cannot use the filter argument of Magento\Catalog\Api\ProductRepositoryInterface::getList() for the category, because it is not an attribute, but an external n:m relation.

So it would require two steps:

  1. load all skus for the category with CategoryLinkManagementInterface::getAssignedProducts().

  2. use ProductRepositoryInterface::getList() to get a list of products with filter conditions:

    • SKU in (previous result) AND
    • (your additional filters)

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.