Skip to content

Commit 4d8962d

Browse files
authored
Merge pull request #3767 from craftcms/bugfix/5x-variant-performance-improvements
[5.x] Improve product variant's query performance
2 parents c31d5a3 + ba07f0a commit 4d8962d

File tree

3 files changed

+69
-2
lines changed

3 files changed

+69
-2
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Unreleased
44

5+
- Improved the performance of `Product::getVariants()`. ([#3578](https://github.com/craftcms/commerce/issues/3758))
56
- Fixed a SQL error that could occur when creating a variant. ([#3763](https://github.com/craftcms/commerce/issues/))
67

78
## 5.2.3 - 2024-11-13

src/elements/Product.php

+15
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,21 @@ public function getVariants(bool $includeDisabled = false): VariantCollection
10451045
}
10461046

10471047
$this->_variants = self::createVariantQuery($this)->status(null)->collect();
1048+
$this->_variants->map(function(Variant $v) {
1049+
if (!$this->id) {
1050+
return $v;
1051+
}
1052+
1053+
if ($v->primaryOwnerId === $this->id) {
1054+
$v->setPrimaryOwner($this);
1055+
}
1056+
1057+
if ($v->ownerId === $this->id) {
1058+
$v->setOwner($this);
1059+
}
1060+
1061+
return $v;
1062+
});
10481063
}
10491064

10501065
return $this->_variants->filter(fn(Variant $variant) => $includeDisabled || ($variant->getStatus() === self::STATUS_ENABLED));

src/elements/Variant.php

+53-2
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@
6060
* @property-read string $gqlTypeName
6161
* @property-read string $skuAsText
6262
* @property string $salePriceAsCurrency
63-
* @method Product|null getOwner()
64-
* @method Product|null getPrimaryOwner()
6563
* @author Pixel & Tonic, Inc. <[email protected]>
6664
* @since 2.0
6765
*/
@@ -524,6 +522,59 @@ public function setOwner(?ElementInterface $owner): void
524522
$this->traitSetOwner($owner);
525523
}
526524

525+
/**
526+
* @inheritdoc
527+
* @TODO remove implementation when `NestedElementTrait::getOwner()` is updated
528+
*/
529+
public function getPrimaryOwner(): ?Product
530+
{
531+
if (!isset($this->_primaryOwner)) {
532+
$primaryOwnerId = $this->getPrimaryOwnerId();
533+
if (!$primaryOwnerId) {
534+
return null;
535+
}
536+
537+
$this->_primaryOwner = Craft::$app->getElements()->getElementById($primaryOwnerId, Product::class, $this->siteId, [
538+
'trashed' => null,
539+
]) ?? false;
540+
if (!$this->_primaryOwner) {
541+
throw new InvalidConfigException("Invalid owner ID: $primaryOwnerId");
542+
}
543+
}
544+
545+
/** @phpstan-ignore-next-line */
546+
return $this->_primaryOwner ?: null;
547+
}
548+
549+
/**
550+
* @inheritdoc
551+
* @TODO remove implementation when `NestedElementTrait::getOwner()` is updated
552+
*/
553+
public function getOwner(): ?Product
554+
{
555+
if (!isset($this->_owner)) {
556+
$ownerId = $this->getOwnerId();
557+
if (!$ownerId) {
558+
return null;
559+
}
560+
561+
// If ownerId and primaryOwnerId are the same, return the primary owner
562+
if ($ownerId === $this->getPrimaryOwnerId()) {
563+
return $this->getPrimaryOwner();
564+
}
565+
566+
$this->_owner = Craft::$app->getElements()->getElementById($ownerId, Product::class, $this->siteId, [
567+
'trashed' => null,
568+
]) ?? false;
569+
if (!$this->_owner) {
570+
throw new InvalidConfigException("Invalid owner ID: $ownerId");
571+
}
572+
}
573+
574+
/** @phpstan-ignore-next-line */
575+
return $this->_owner ?: null;
576+
}
577+
527578
/**
528579
* Returns the product associated with this variant.
529580
*

0 commit comments

Comments
 (0)