Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
66.67% covered (warning)
66.67%
6 / 9
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
ProductVariation
66.67% covered (warning)
66.67%
6 / 9
0.00% covered (danger)
0.00%
0 / 3
3.33
0.00% covered (danger)
0.00%
0 / 1
 product
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 attributeValues
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 boot
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
1.00
1<?php
2
3namespace App\Models;
4
5use App\Models\admin\Product;
6use App\Service\CacheService;
7use Illuminate\Database\Eloquent\Factories\HasFactory;
8use Illuminate\Database\Eloquent\Model;
9
10class ProductVariation extends Model
11{
12    use HasFactory;
13
14    // BUG FIX: was `$guarded = []` (everything mass-assignable). Explicit list is safer.
15    protected $fillable = ['product_id', 'sku', 'price', 'stock_quantity', 'stock_status'];
16
17    public function product()
18    {
19        return $this->belongsTo(Product::class);
20    }
21
22    public function attributeValues()
23    {
24        return $this->belongsToMany(AttributeValue::class, 'product_variation_attribute_value');
25    }
26
27    // CACHING: a variation's own price/stock/status changes independently of
28    // its parent Product row (e.g. ProductController::updateStockAjax()'s
29    // stock-toggle just calls $variation->save(), never touching Product).
30    // Bust that product's cached detail/quick-view pages immediately so the
31    // storefront never shows stale variant data.
32    protected static function boot()
33    {
34        parent::boot();
35
36        static::saved(function ($variation) {
37            CacheService::forgetProduct($variation->product_id);
38        });
39
40        static::deleted(function ($variation) {
41            CacheService::forgetProduct($variation->product_id);
42        });
43    }
44}