如何计算购物车中商品与课程的总金额?
购物车总金额计算问题
问题背景
我有两张products表和一张courses表,每个购物车可添加多个商品和课程。商品/课程的单价×订购数量后的单项总价,已经正确存储在中间表的total字段中。现在需要计算每个订单的总金额,生成订单概览,但现有代码计算结果始终为0,移除判断后又报数组键不存在的错误。
首次尝试的代码
@php $totalPrice = 0; foreach (App\Services\Cart\Cart::all() as $cart) { if (isset($cart['product']) && isset($cart['course'])) { $productPrice = intval($cart['product']->price); $coursePrice = intval($cart['course']->price); $totalPrice += ($productPrice + $coursePrice) * $cart['quantity']; } } $totalPrice = number_format($totalPrice); @endphp <div class="text-large"><strong>{{ $totalPrice }} $</strong></div>
移除判断后的代码
@php $totalPrice = 0; foreach (App\Services\Cart\Cart::all() as $cart) { $productPrice = intval($cart['product']->price); $coursePrice = intval($cart['course']->price); $totalPrice += ($productPrice + $coursePrice) * $cart['quantity']; } $totalPrice = number_format($totalPrice); @endphp <div class="text-large"><strong>{{ $totalPrice }} $</strong></div>
Cart服务类代码(App\Services\Cart\Cart.php)
<?php namespace App\Services\Cart; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Str; class Cart { protected $cart; public function __construct() { $this->cart = session()->get('cart') ?? collect([]); } /** * @param array $value * @param null $obj * @return $this */ public function put(array $value , $obj = null) { if(!is_null($obj) && $obj instanceof Model) { $value = array_merge($value , [ 'id' => Str::random(10), 'subject_id' => $obj->id, 'subject_type' => get_class($obj) ]); } elseif(!isset($value['id'])) { $value = array_merge($value , [ 'id' => Str::random(10) ]); } $this->cart->put($value['id'] , $value); session()->put('cart' , $this->cart); return $this; } public function update($key, $options) { $item = collect($this->get($key, false)); if (is_numeric($options)) { $item = $item->merge([ 'quantity' => $item['quantity'] + $options ]); } if (is_array($options)) { $item = $item->merge($options); } $this->put($item->toArray()); return $this; } public function count($key) { if (!$this->has($key)) return 0; return $this->get($key)['quantity']; } public function has($key) { if($key instanceof Model) { return ! is_null( $this->cart->where('subject_id' , $key->id)->where('subject_type' , get_class($key))->first() ); } return ! is_null( $this->cart->firstWhere('id' , $key) ); } public function get($key, $withRelationship = true) { $item = $key instanceof Model ? $this->cart->where('subject_id' , $key->id)->where('subject_type' , get_class($key))->first() : $this->cart->firstWhere('id' , $key); return $withRelationship ? $this->withRelationshipIfExist($item) : $item; } public function all() { $cart = $this->cart; $cart = $cart->map(function($item) { return $this->withRelationshipIfExist($item); }); return $cart; } protected function withRelationshipIfExist($item) { if(isset( $item['subject_id'] ) && isset($item['subject_type']) ) { $class = $item['subject_type']; $subject = (new $class())->find( $item['subject_id'] ); $item[strtolower(class_basename($class))] = $subject; unset($item['subject_id']); unset($item['subject_type']); return $item; } return $item; } public function delete($key) { if ($this->has($key)) { $this->cart = $this->cart->filter(function ($item) use ($key){ if ($key instanceof Model) { return ($item['subject_id'] != $key->id ) && ($item['subject_type'] != get_class($key)); } return $key != $item['id']; }); session()->put('cart', $this->cart); return true; } return false; } public function flush() { $this->cart = collect([]); session()->put('cart', $this->cart); return $this; } }
移除判断后出现的错误
Undefined array key "course"
解决方案
问题核心:每个购物车项要么是商品(仅含product键),要么是课程(仅含course键),不会同时存在两者。之前的代码要么要求两者都存在才计算(导致所有项都不满足,结果为0),要么强制访问两个不存在的键(触发报错)。
结合你提到的「单项总价已存储在total字段」,推荐直接读取该字段计算总金额,更高效且避免重复计算:
方案1:修改视图计算代码
@php $totalPrice = 0; foreach (App\Services\Cart\Cart::all() as $cartItem) { // 优先读取已存储的单项总价 if (isset($cartItem['total'])) { $totalPrice += intval($cartItem['total']); } else { // 兼容无total字段的情况,分别处理商品/课程 $itemPrice = 0; if (isset($cartItem['product'])) { $itemPrice = intval($cartItem['product']->price) * intval($cartItem['quantity']); } elseif (isset($cartItem['course'])) { $itemPrice = intval($cartItem['course']->price) * intval($cartItem['quantity']); } $totalPrice += $itemPrice; } } $totalPrice = number_format($totalPrice); @endphp <div class="text-large"><strong>{{ $totalPrice }} $</strong></div>
方案2:在Cart类中新增总金额计算方法(更优雅)
在Cart类中添加以下方法:
// 计算购物车总金额 public function getTotal() { return $this->cart->sum(function($item) { // 优先使用已存储的单项总价 if (isset($item['total'])) { return intval($item['total']); } // 无total字段时,关联模型后计算 $itemWithRel = $this->withRelationshipIfExist($item); if (isset($itemWithRel['product'])) { return intval($itemWithRel['product']->price) * intval($itemWithRel['quantity']); } elseif (isset($itemWithRel['course'])) { return intval($itemWithRel['course']->price) * intval($itemWithRel['quantity']); } return 0; }); }
然后在视图中直接调用:
@php $cart = app(App\Services\Cart\Cart::class); $totalPrice = number_format($cart->getTotal()); @endphp <div class="text-large"><strong>{{ $totalPrice }} $</strong></div>
内容的提问来源于stack exchange,提问作者irankhostravi
相关产品推荐
相关产品推荐

