0

I am building an e-commerce app to sell products. There is a section in my website with products on sale and I want to show in this section just the products that are on sale. But in the backend of my app, the products on sale (Special) have the same value as the normal products (Price). So, to set those two apart I create a field custom atributes with the name type.

{"attribute_code": "type",
"value": "Special"
}

So how can I make the query bring only the products that have the value Special?

below is the code that filters but it's not bringing the products with the value Special

products(
        pageSize: $size
        currentPage: $page
        search: $filterBrand
        sort: { name: $sortByName, price: $sortByPrice }
        filter: { category_id: { eq: $id}, type: {eq : "Special"}}
    ) 

3 Answers 3

0

We cannot get the results for custom_attributes with default products graphql query.

You want to create a custom module to achieve this.

We want to define, undefined(in Native GraphQl) products attribute in the di.xml.

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<virtualType name="Magento\Catalog\Model\Api\SearchCriteria\CollectionProcessor\ProductFilterProcessor" type="Magento\Eav\Model\Api\SearchCriteria\CollectionProcessor\FilterProcessor">
    <arguments>
        <argument name="customFilters" xsi:type="array">
            <item name="language" xsi:type="object">
                Ayakil\CatalogGraphQl\Model\Resolver\Products\SearchCriteria\CollectionProcessor\FilterProcessor\ProductAttributeFilter
            </item>
        </argument>
    </arguments>
</virtualType>

Here language is custom attribute.

After this we want to define the custom attribute as FilterTypeInput to ProductFilterInput in the shchema.graphqls file like below.

input ProductFilterInput {

  language: FilterTypeInput @doc(description: "Product Language")

}

After this we want to create ProductAttributeFilter.php file under the Model directory. As we defined in the di.xml file.

<?php
declare(strict_types=1);
namespace Ayakil\CatalogGraphQl\Model\Resolver\Products\SearchCriteria\CollectionProcessor\FilterProcessor;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\Framework\Api\SearchCriteria\CollectionProcessor\FilterProcessor\CustomFilterInterface;
use Magento\Framework\Data\Collection\AbstractDb;
use Magento\Framework\Api\Filter;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable;
use Magento\Framework\Registry;
/**
* Category filter allows to filter products collection using custom defined filters from search criteria.
*/
class ProductAttributeFilter implements CustomFilterInterface
{
protected $configurable;
protected $collectionFactory;
protected $registry;

public function __construct(
    Configurable $configurable,
    CollectionFactory $collectionFactory,
    \Psr\Log\LoggerInterface $logger,
    Registry $registry
) {
    $this->registry = $registry;
    $this->configurable = $configurable;
    $this->logger = $logger;
    $this->collectionFactory = $collectionFactory;
}

public function apply(Filter $filter, AbstractDb $collection)
{
    $conditionType = $filter->getConditionType();
    $attributeName = $filter->getField();
    $attributeValue = $filter->getValue();
    $category = $this->registry->registry('current_category');


    if($attributeName == 'language'){
        $conditions = [];
        foreach ($attributeValue as $value){
            $conditions[] = ['attribute'=>$attributeName, 'finset'=>$value];
        }
        $simpleSelect = $this->collectionFactory->create()
                        ->addAttributeToFilter($conditions);

    }else{
        $simpleSelect = $this->collectionFactory->create()
            ->addAttributeToFilter($attributeName, [$conditionType => $attributeValue]);
    }

    $simpleSelect->addAttributeToFilter('status', Status::STATUS_ENABLED);
    if ($category) {
        $simpleSelect->addCategoriesFilter(['in' => (int)$category->getId()]);
    }


    $arr =  $simpleSelect;
    $entity_ids = [];
    foreach ($arr->getData() as $a){
        $entity_ids[] = $a['entity_id'];
    }

    $collection->getSelect()->where($collection->getConnection()->prepareSqlCondition(
        'e.entity_id', ['in' => $entity_ids]
    ));

    return true;
}
}

Now you can add this added custom product attribute language to Products graphql query.

To clearly read about this visit magento 2 product collection filter by attribute using graphql.

You can read more articles about graphql with these articles below.

1 . Magento get product attribute value by code, magento 2 get attribute value by id using graphql

2 . How to create graphql module in magento 2?

3 . magento 2 search criteria custom attribute using graphql

4 . Magento 2 graphql example for integrate contact us page functionality.

0

Starting from Magento 2.3.4 this is now possible without creating a custom module!

It is only possible for product attributes, it is not yet possible to do custom filtering by default on things like categories.

You can read about it in the Magento docs: https://devdocs.magento.com/guides/v2.4/graphql/custom-filters.html

0

Magento 2.4

Filter, sort, and get product custom attribute

Create Custom Attribute with below options values.

enter image description here

enter image description here

app/code/VendoreName/ModuleName/etc

schema.graphqls

interface ProductInterface {
    sample_attribute: String @doc(description: "Product Custom Attribute Show")
      @resolver(
        class: "VendoreName\\ModuleName\\Model\\Resolver\\Product\\AddCustomAttribute"
      )
}

input ProductAttributeFilterInput {
  sample_attribute: FilterEqualTypeInput @doc(description: "Product Data filter with Custom Attribute Value")
}

input ProductAttributeSortInput {
  sample_attribute: SortEnum @doc(description: "Sort by the Product Custom Attribute.")
}

app/code/VendoreName/ModuleName/Model/Resolver/Product

AddCustomAttribute.php

<?php

namespace VendoreName\ModuleName\Model\Resolver\Product;

use Magento\Framework\GraphQl\Query\ResolverInterface;

/**
 * Product custom attribute field resolver
 */
class AddCustomAttribute implements ResolverInterface
{

    /**
     * @var Magento\Catalog\Model\ProductFactory
     */
    protected $productFactory;

    /**
     * @param Magento\Catalog\Model\ProductFactory $productFactory
     */
    public function __construct(
        \Magento\Catalog\Model\ProductFactory $productFactory
    ) {
        $this->productFactory = $productFactory;
    }

    /**
     * @inheritdoc
     */
    public function resolve(
        \Magento\Framework\GraphQl\Config\Element\Field $field,
        $context,
        \Magento\Framework\GraphQl\Schema\Type\ResolveInfo $info,
        array $value = null,
        array $args = null
    ) {
        $product = $value['model'];
        $_product = $this->productFactory->create()->load($product->getId());
        return $_product->getData('sample_attribute');
    }
}

Run Magento Commands:

php bin/magento s:up
php bin/magento in:rein
php bin/magento s:s:d -f
php bin/magento c:c

For show product custom attribute value

{
  products(filter: { sku: { eq: "24-MB01" } }) {
    items {
      name
      sku
      sample_attribute
    }
  }
}

For filter product data using custom attribute

{
  products(filter: { sample_attribute: { eq: "test" } }) {
    items {
      name
      sku
      sample_attribute
    }
  }
}

For sort product data using custom attribute

{
  products(search: "bag", sort: {sample_attribute: DESC}) {
    items {
      name
      sku
      sample_attribute
    }
  }
}
1

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.