Procházet zdrojové kódy

修改productCount

bianjunhui před 2 dny
rodič
revize
6a5dd1f537

+ 37 - 8
packages/Webkul/BagistoApi/src/Models/AttributeOption.php

@@ -8,6 +8,8 @@ use ApiPlatform\Metadata\Get;
 use ApiPlatform\Metadata\GetCollection;
 use ApiPlatform\OpenApi\Model;
 use Illuminate\Database\Eloquent\Model as EloquentModel;
+use Symfony\Component\TypeInfo\Type\BuiltinType;
+use Symfony\Component\TypeInfo\TypeIdentifier;
 
 #[ApiResource(
     shortName: 'AttributeOption',
@@ -42,23 +44,50 @@ use Illuminate\Database\Eloquent\Model as EloquentModel;
         ),
     ],
 )]
+#[ApiProperty(property: 'product_count', writable: false, readable: true, nativeType: new BuiltinType(TypeIdentifier::INT))]
 class AttributeOption extends \Webkul\Attribute\Models\AttributeOption
 {
     /**
-     * Number of visible products associated with this option within the
-     * current category context. Populated by FilterableAttributesProvider.
+     * Static cache of product counts resolved by FilterableAttributesProvider.
+     *
+     * Keyed by attribute id, then option id. The provider computes the counts
+     * once per request and stores them here so the GraphQL "options" relation
+     * (which re-queries options through a separate cursor-connection provider
+     * and therefore produces fresh model instances) can still surface the
+     * correct product count.
+     *
+     * @var array<int, array<int, int>>
      */
-    #[ApiProperty(writable: false, readable: true)]
-    public int $product_count = 0;
+    private static array $resolvedProductCounts = [];
 
     /**
-     * Laravel accessor for the product_count virtual attribute. The accessor
-     * naming convention makes API Platform discover it as a virtual attribute,
-     * while the public property above lets PropertyInfo infer the int type.
+     * Store the resolved product counts for the given attribute's options.
+     *
+     * @param  array<int, int>  $counts  option id => count
+     */
+    public static function setResolvedProductCounts(int $attributeId, array $counts): void
+    {
+        static::$resolvedProductCounts[$attributeId] = $counts;
+    }
+
+    /**
+     * Number of visible products associated with this option within the
+     * current category context.
+     *
+     * Prefer the value computed and cached by FilterableAttributesProvider;
+     * this keeps the count correct even when the option is fetched through
+     * the GraphQL cursor-connection relation instead of the eager-loaded
+     * collection.
      */
     public function getProductCountAttribute(): int
     {
-        return (int) ($this->product_count ?? 0);
+        $attributeId = (int) ($this->attribute_id ?? 0);
+
+        if (isset(static::$resolvedProductCounts[$attributeId][(int) $this->id])) {
+            return (int) static::$resolvedProductCounts[$attributeId][(int) $this->id];
+        }
+
+        return 0;
     }
 
     #[ApiProperty(identifier: true, writable: false)]

+ 6 - 1
packages/Webkul/BagistoApi/src/State/FilterableAttributesProvider.php

@@ -171,9 +171,14 @@ class FilterableAttributesProvider implements ProviderInterface
             $counts = $this->countMultiSelectOptions(clone $countQuery, $optionIds, $alias);
         }
 
+        $normalized = [];
+
         foreach ($options as $option) {
-            $option->product_count = (int) ($counts[(string) $option->id] ?? 0);
+            $count = (int) ($counts[(string) $option->id] ?? 0);
+            $normalized[(int) $option->id] = $count;
         }
+
+        \Webkul\BagistoApi\Models\AttributeOption::setResolvedProductCounts((int) $attributeId, $normalized);
     }
 
     /**