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
Best Answer
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 withOR
, namely with a single argument: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 magento-2.2):
Magento\Catalog\Api\CategoryLinkManagementInterface::getAssignedProducts()
to retrieve a sorted list of SKUs for a given category id, but it does not accept additional filtersMagento\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:
load all skus for the category with
CategoryLinkManagementInterface::getAssignedProducts()
.use
ProductRepositoryInterface::getList()
to get a list of products with filter conditions: