In my schema.graphqls file I've created this Query
type Query {
getLinkedProductsByGroups(groups: [String]): [LinkedProductsByGroup] @resolver(class: "Vendor\\ProductDisplay\\Model\\Resolver\\LinkedProductsByGroups")
}
type LinkedProductsByGroup {
group: String
products: [ProductInterface]
}
I've created my resolver
<?php
/*
* Copyright (c) 2023. Vendor TECHNOLOGIES
*/
namespace Vendor\ProductDisplay\Model\Resolver;
use Vendor\ProductDisplay\Service\LinkedProductsLocator;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\CatalogGraphQl\Model\Resolver\Product\ProductFieldsSelector;
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Deferred\Product as ProductDataProvider;
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\ProductSearch;
use Magento\Framework\Api\SearchCriteriaBuilderFactory;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Query\Resolver\BatchResolverInterface;
use Magento\Framework\GraphQl\Query\Resolver\BatchResponse;
use Magento\Framework\GraphQl\Query\Resolver\ContextInterface;
use Magento\Framework\GraphQl\Query\Resolver\ValueFactory;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
class LinkedProductsByGroups implements ResolverInterface
{
protected LinkedProductsLocator $linkedProductsLocator;
protected ProductRepositoryInterface $productRepository;
protected SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory;
public function __construct(
SearchCriteriaBuilderFactory $searchCriteriaBuilderFactory,
ProductRepositoryInterface $productRepository,
LinkedProductsLocator $linkedProductsLocator
)
{
$this->linkedProductsLocator = $linkedProductsLocator;
$this->searchCriteriaBuilderFactory = $searchCriteriaBuilderFactory;
$this->productRepository = $productRepository;
}
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
{
$result = [];
$groups = $args['groups'];
foreach ($groups as $group) {
$resultItem = [];
$resultItem['group'] = $group;
$resultItem['products'] = [];
//fetch related products
$linkedProductIds = $this->linkedProductsLocator->getLinkedProductIdsByGroup($group);
$scb = $this->searchCriteriaBuilderFactory->create();
$scb->addFilter('entity_id', $linkedProductIds, 'in');
$searchResults = $this->productRepository->getList($scb->create());
if ($searchResults->getTotalCount() > 0) {
foreach ($searchResults->getItems() as $item) {
$data = $item->toArray();
$data['model'] = 'product';
$resultItem['products'][] = $data;
}
}
$result[] = $resultItem;
}
return $result;
}
}
This pretty much works but I have a problem fetching composite fields like price or small_image.
When I run my query without them everything is fine.
But with them I get this error
query {
getLinkedProductsByGroups(groups: ["001021", "001107"]) {
group
products {
name
sku
small_image {
url
}
}
}
}
This error comes up
{
"errors": [
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
0,
"products",
0,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
0,
"products",
1,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
0,
"products",
2,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
0,
"products",
3,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
0,
"products",
4,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
0,
"products",
5,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
0,
"products",
6,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
0,
"products",
7,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
0,
"products",
8,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
0,
"products",
9,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
0,
"products",
10,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
0,
"products",
11,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
1,
"products",
0,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
1,
"products",
1,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
1,
"products",
2,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
1,
"products",
3,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
1,
"products",
4,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
1,
"products",
5,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
1,
"products",
6,
"small_image",
"url"
]
},
{
"debugMessage": "Call to a member function getData() on string",
"message": "Internal server error",
"extensions": {
"category": "internal"
},
"locations": [
{
"line": 8,
"column": 11
}
],
"path": [
"getLinkedProductsByGroups",
1,
"products",
7,
"small_image",
"url"
]
}
],
"data": {
"getLinkedProductsByGroups": [
{
"group": "001021",
"products": [
{
"name": "Bidi Badu Bella Women's Tech Neck T-shirt",
"sku": "001021-PKIB",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Bella Women's Tech Neck T-shirt",
"sku": "001021-PKYW",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Bella Women's Tech Neck T-shirt",
"sku": "001021-PKDBL",
"small_image": {
"url": null
}
},
{
"name": "BIDI BADU Bella Tech Neck Women's T-shirt-XS",
"sku": "001021-PKDBL-XS",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Bella Women's Tech Neck T-shirt",
"sku": "001021-BKDBL",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Bella Women's Tech Neck T-shirt",
"sku": "001021-DBPK",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Bella Women's Tech Neck T-shirt",
"sku": "001021-CON",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Bella Women's Tech Neck T-shirt",
"sku": "001021-GRCO",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Bella Women's Tech Neck T-shirt",
"sku": "001021-PKGR",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Bella Tech Neck Women's T-shirt-XS",
"sku": "001021-PKGR-XS",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Bella Women's Tech Neck T-shirt",
"sku": "001021-RDPK",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Bella Women's Tech Neck T-shirt",
"sku": "001021-ANDB",
"small_image": {
"url": null
}
}
]
},
{
"group": "001107",
"products": [
{
"name": "Bidi Badu Magu Crew Tech Sport Socks x 3",
"sku": "001107-WH",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Magu Crew Tech Socks - set of 3-39-42",
"sku": "001107-WH-39-42",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Magu Crew Tech Socks - set of 3-43-46",
"sku": "001107-WH-43-46",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Magu Crew Tech Socks - set of 3-46-50",
"sku": "001107-WH-46-50",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Magu Crew Tech Sport Socks x 3",
"sku": "001107-BK",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Magu Crew Tech Socks - set of 3-39-42",
"sku": "001107-BK-39-42",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Magu Crew Tech Socks - set of 3-43-46",
"sku": "001107-BK-43-46",
"small_image": {
"url": null
}
},
{
"name": "Bidi Badu Magu Crew Tech Socks - set of 3-46-50",
"sku": "001107-BK-46-50",
"small_image": {
"url": null
}
}
]
}
]
}
}
Of course I can't use the price / image fields directly because the ProductInterface type must have a sub-selection for them. But the toArray() and the getData() functions don't give the result as expected. So how do I make it convert the fields properly from the ProductInterface defined in the PHP classes, to the ProductInterface defined in GraphQl so that the result is correct?