Skip to content

Commit 9cb3f3b

Browse files
authored
Fix configurable links N+1 in custom product endpoint (#482)
1 parent f4de08f commit 9cb3f3b

3 files changed

Lines changed: 28 additions & 12 deletions

File tree

Doofinder/Feed/Model/ProductRepository.php

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Magento\Catalog\Model\ProductFactory;
1515
use Magento\Catalog\Model\ProductRepository as ProductRepositoryBase;
1616
use Magento\Catalog\Model\ResourceModel\Product as ProductResourceModel;
17+
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollectionFactory;
1718
use Magento\Framework\Api\SearchCriteriaBuilder;
1819
use Magento\Framework\Api\SearchCriteriaInterface;
1920
use Magento\Framework\App\Area;
@@ -66,6 +67,9 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa
6667
/** @var \Magento\Catalog\Model\ProductFactory */
6768
protected $productFactory;
6869

70+
/** @var \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory */
71+
protected $productCollectionFactory;
72+
6973
/** @var \Magento\Framework\Api\SearchCriteriaBuilder */
7074
protected $searchCriteriaBuilder;
7175

@@ -107,6 +111,7 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa
107111
* @param MagentoStoreConfig $magentoStoreConfig Magento core store config.
108112
* @param ScopeConfigInterface $scopeConfig Magento core scope config.
109113
* @param ProductFactory $productFactory Product factory instance.
114+
* @param ProductCollectionFactory $productCollectionFactory Product collection factory instance.
110115
* @param SearchCriteriaBuilder $searchCriteriaBuilder Search criteria builder.
111116
* @param ProductResourceModel $resourceModel Product resource model.
112117
* @param StoreManagerInterface $storeManager Store manager interface.
@@ -126,6 +131,7 @@ public function __construct(
126131
MagentoStoreConfig $magentoStoreConfig,
127132
ScopeConfigInterface $scopeConfig,
128133
ProductFactory $productFactory,
134+
ProductCollectionFactory $productCollectionFactory,
129135
SearchCriteriaBuilder $searchCriteriaBuilder,
130136
ProductResourceModel $resourceModel,
131137
StoreManagerInterface $storeManager,
@@ -143,6 +149,7 @@ public function __construct(
143149
$this->magentoStoreConfig = $magentoStoreConfig;
144150
$this->scopeConfig = $scopeConfig;
145151
$this->productFactory = $productFactory;
152+
$this->productCollectionFactory = $productCollectionFactory;
146153
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
147154
$this->resourceModel = $resourceModel;
148155
$this->storeManager = $storeManager;
@@ -688,20 +695,29 @@ private function getProductImagesLinks(ProductInterface $product, ?string $image
688695
*/
689696
private function getEnabledConfigurableLinks($configurableLinksIds)
690697
{
691-
$enabledProductIds = [];
692-
693-
if (null === $configurableLinksIds) {
694-
return $enabledProductIds;
698+
if (empty($configurableLinksIds)) {
699+
return [];
695700
}
696701

702+
/* Resolve the enabled status of every linked product in a single query
703+
* instead of loading each product individually (N+1), which is
704+
* prohibitively slow for configurables with many variants.
705+
* Status is read at the current (emulated) store scope so that
706+
* store-view level overrides are respected, matching the previous
707+
* getById() behaviour.
708+
*/
709+
$collection = $this->productCollectionFactory->create();
710+
$collection->setStoreId((int) $this->storeManager->getStore()->getId());
711+
$collection->addIdFilter($configurableLinksIds);
712+
$collection->addAttributeToFilter('status', Status::STATUS_ENABLED);
713+
$enabledIds = array_flip(array_map('intval', $collection->getAllIds()));
714+
715+
// Keep the original order of the configurable links.
716+
$enabledProductIds = [];
697717
foreach ($configurableLinksIds as $productId) {
698-
$product = $this->getById($productId);
699-
700-
if (Status::STATUS_ENABLED !== (int) $product->getStatus()) {
701-
continue;
718+
if (isset($enabledIds[(int) $productId])) {
719+
$enabledProductIds[] = $productId;
702720
}
703-
704-
$enabledProductIds[] = $productId;
705721
}
706722

707723
return $enabledProductIds;

Doofinder/Feed/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "doofinder/doofinder-magento2",
3-
"version": "1.7.4",
3+
"version": "1.7.5",
44
"description": "Doofinder module for Magento 2",
55
"type": "magento2-module",
66
"require": {

Doofinder/Feed/etc/module.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0"?>
22
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
3-
<module name="Doofinder_Feed" setup_version="1.7.4">
3+
<module name="Doofinder_Feed" setup_version="1.7.5">
44
<sequence>
55
<module name="Magento_Integration" />
66
</sequence>

0 commit comments

Comments
 (0)