Laravel 10中如何自动更新restock字段:库存达最低值时设为1
Laravel 10 自动设置restock字段的逻辑实现位置
需求:当商品的stock(库存)等于min_stock(最低库存)时,自动将restock字段设为1;否则设为0。
现有代码
数据库迁移代码
Schema::create('products', function (Blueprint $table) { $table->id(); $table->string('product_name'); $table->string('category_id'); $table->string('unit_id'); $table->string('product_code')->nullable(); $table->double('min_stock'); $table->double('stock'); $table->integer('restock')->default(0)->comment('0=No, 1=Yes'); $table->string('product_image')->nullable(); $table->timestamps(); });
出库场景控制器代码
public function updateOrder(Request $request) { $order_id = $request->id; // Reduce the stock $products = OrderDetails::where('order_id', $order_id)->get(); foreach ($products as $product) { Product::where('id', $product->product_id) ->update(['stock' => DB::raw('stock-'.$product->quantity)]); } Order::findOrFail($order_id)->update(['order_status' => 'complete']); return Redirect::route('order.completeOrders')->with('success', 'Order has been completed!'); }
入库场景控制器代码
public function updatePurchase(Request $request) { $purchase_id = $request->id; // after purchase approved, add stock product $products = PurchaseDetails::where('purchase_id', $purchase_id)->get(); foreach ($products as $product) { Product::where('id', $product->product_id) ->update(['stock' => DB::raw('stock+'.$product->quantity)]); } Purchase::findOrFail($purchase_id) ->update([ 'purchase_status' => 1, 'updated_by' => auth()->user()->id ]); // 1 = approved, 0 = pending return Redirect::route('purchases.allPurchases')->with('success', 'Purchase has been approved!'); }
实现方案
推荐在模型层面处理这个逻辑,这样不管通过哪种方式修改库存(控制器、后台编辑、API等),都能自动同步restock字段,避免重复代码和遗漏场景。
方案1:模型观察者(推荐)
- 生成Product模型观察者:
php artisan make:observer ProductObserver --model=Product
- 在
app/Observers/ProductObserver.php中添加逻辑:
namespace App\Observers; use App\Models\Product; class ProductObserver { // 在模型保存(创建/更新)前触发 public function saving(Product $product): void { $product->restock = $product->stock == $product->min_stock ? 1 : 0; } }
- 在
app/Providers/AppServiceProvider.php的boot方法中注册观察者:
use App\Models\Product; use App\Observers\ProductObserver; public function boot(): void { Product::observe(ProductObserver::class); }
方案2:模型内置事件
如果不想单独创建观察者,可以直接在Product模型中通过booted方法注册事件:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Product extends Model { protected static function booted(): void { static::saving(function (Product $product) { $product->restock = $product->stock == $product->min_stock ? 1 : 0; }); } }
方案3:直接在控制器中处理(不推荐)
如果只在当前的出库/入库场景处理,可以修改控制器代码,但后续新增库存修改场景时需要重复编写逻辑:
出库控制器修改:
foreach ($products as $product) { $productModel = Product::find($product->product_id); $newStock = $productModel->stock - $product->quantity; $productModel->update([ 'stock' => $newStock, 'restock' => $newStock == $productModel->min_stock ? 1 : 0 ]); }
入库控制器修改:
foreach ($products as $product) { $productModel = Product::find($product->product_id); $newStock = $productModel->stock + $product->quantity; $productModel->update([ 'stock' => $newStock, 'restock' => $newStock == $productModel->min_stock ? 1 : 0 ]); }
内容的提问来源于stack exchange,提问作者Yahya Setya Nurohman
相关产品推荐
相关产品推荐

