query = $query ?: new Goods(); $this->format = $format; } /** * with 关联 * * @param mixed $with * @return self */ public function with($with) { $this->query->with($with); return $this; } /** * 查询上架的商品,包含隐藏商品 * * @return self */ public function show() { $this->md5s[] = 'show'; $this->query = $this->query->whereIn('status', [1]); return $this; } /** * 查询上架的商品,不包含隐藏商品 * * @return self */ public function up() { $this->md5s[] = 'up'; $this->query = $this->query->where('status', 1); return $this; } /** * 查询库存大于0的商品 * * @return self */ public function inStock() { $this->md5s[] = 'inStock'; $this->query = $this->query->where('stock', '>', 0); return $this; } /** * 搜索商品 * * @param string $keyword * @return self */ public function search($keyword) { $keyword = is_string($keyword) ? $keyword : json_encode($keyword); $this->md5s[] = 'search:' . $keyword; $this->query = $this->query->where('name', 'like', '%' . $keyword . '%'); return $this; } /** * 根据 ids 获取商品 * * @param string|array $ids ids 数组或者 , 隔开的字符串 * @return self */ public function whereIds($ids = '') { $ids = array_map('intval', is_array($ids) ? $ids : explode(',', $ids)); $this->md5s[] = 'ids:' . implode(',', $ids); if (!empty($ids)) { $this->query = $this->query->orderRaw('field(id, ' . implode(',', $ids) . ')'); $this->query = $this->query->whereIn('id', $ids); } return $this; } /** * 根据商品分类获取商品 * * @param integer $category_id * @param boolean $is_category_deep 是否深度搜索子分类 * @return self */ public function category($category_id, $is_category_deep = true) { $category_id = intval($category_id); $this->md5s[] = 'category_id:' . $category_id; $category_ids = []; if (isset($category_id) && $category_id != 0) { if ($is_category_deep) { // 查询分类所有子分类,包括自己 $category_ids = $this->getChildIds($category_id); } else { $category_ids = [$category_id]; } } $this->query->where(function ($query) use ($category_ids) { // 所有子分类使用 find_in_set or 匹配 foreach ($category_ids as $key => $category_id) { $query->whereOrRaw("find_in_set($category_id, category_id)"); } }); return $this; } /** * 获取分类及其所有子分类ID * * @param int $categoryId * @return array */ protected function getChildIds($categoryId) { $categoryIds = [$categoryId]; $this->getChildCategoryIds($categoryId, $categoryIds); return $categoryIds; } /** * 递归获取子分类ID * * @param int $parentId * @param array $categoryIds */ protected function getChildCategoryIds($parentId, &$categoryIds) { $children = Category::where('parent_id', $parentId) ->where('status', 1) ->where('uniacid', UNIACID) ->column('id'); foreach ($children as $childId) { $categoryIds[] = $childId; $this->getChildCategoryIds($childId, $categoryIds); } } /** * 排序,方法参数同 thinkphp order 方法 * * @param string $sort * @param string $order * @return self */ public function order($sort = 'weigh', $order = 'desc') { $sort = $sort == 'price' ? Db::raw('convert(`price`, DECIMAL(10, 2)) ' . $order) : $sort; $this->query->order($sort, $order); return $this; } /** * 获取商品列表 * * @param bool $is_cache 是否缓存 * @return array|\think\model\Collection */ public function select($is_cache = false) { $this->md5s[] = 'select'; // 默认排序 $this->order(); $goods = $this->query->select(); // 格式化数据 foreach ($goods as $key => $gd) { $gd = $this->defaultFormat($gd); if ($this->format instanceof \Closure) { $gd = ($this->format)($gd, $this); } $goods[$key] = $gd; } return $goods; } /** * 获取商品列表(分页) * * @param bool $is_cache 是否缓存 * @return \think\Paginator */ public function paginate($is_cache = false) { $this->md5s[] = 'paginate'; // 默认排序 $this->order(); $goods = $this->query->paginate(request()->param('list_rows', 10)); // 格式化数据 $goods->each(function ($god) { $god = $this->defaultFormat($god); if ($this->format instanceof \Closure) { ($this->format)($god, $this); } }); return $goods; } /** * 获取单个商品 * * @param bool $is_cache * @return Goods */ public function find($is_cache = false) { $this->md5s[] = 'find'; $goods = $this->query->find(); if ($goods && $this->format instanceof \Closure) { // 格式化数据 $goods = $this->defaultFormat($goods); ($this->format)($goods, $this); } return $goods; } /** * 获取单个商品,找不到抛出异常 * * @param bool $is_cache * @return Goods */ public function findOrFail($is_cache = false) { $this->md5s[] = 'find'; $goods = $this->query->find(); if (!$goods) { throw new \Exception('商品不存在'); } if ($this->format instanceof \Closure) { // 格式化数据 $goods = $this->defaultFormat($goods); ($this->format)($goods, $this); } return $goods; } /** * 默认格式化数据 * * @param array|object $goods * @return array */ public function defaultFormat($goods) { // 获取配置 $physicalConfig = \app\common\model\app\Config::getConfig('physical'); $showSales = $physicalConfig['show_sales'] ?? 1; // 处理图片 if (isset($goods['carousel']) && is_string($goods['carousel'])) { $goods['carousel'] = json_decode($goods['carousel'], true) ?: []; } // 处理分类ID if (isset($goods['category_id']) && is_string($goods['category_id'])) { $goods['category_id'] = array_map('intval', explode(',', $goods['category_id'])); } // 处理参数 if (isset($goods['params']) && is_string($goods['params'])) { $goods['params'] = json_decode($goods['params'], true) ?: []; } // 根据配置决定是否显示销量 if ($showSales != 1) { unset($goods['total_sales']); } // 获取最低价格、库存和销量 if (isset($goods['id'])) { $goodsId = $goods['id']; // 优先使用商品表中的 price 字段 if (isset($goods['price']) && $goods['price'] > 0) { $goods['price'] = floatval($goods['price']); } else { // 如果商品表中没有价格,则从 SKU 价格表中计算 $skuPrices = \app\admin\model\app\physical\SkuPrice::where('goods_id', $goodsId) ->where('uniacid', UNIACID) ->where('status', 1) ->select(); if ($skuPrices) { if (is_array($skuPrices)) { $skuPricesArray = $skuPrices; } else { $skuPricesArray = $skuPrices->toArray(); } $goods['price'] = min(array_column($skuPricesArray, 'price')); } else { $goods['price'] = 0; } } // 计算库存和销量 $skuPrices = \app\admin\model\app\physical\SkuPrice::where('goods_id', $goodsId) ->where('uniacid', UNIACID) ->where('status', 1) ->select(); if ($skuPrices) { if (is_array($skuPrices)) { $skuPricesArray = $skuPrices; } else { $skuPricesArray = $skuPrices->toArray(); } $goods['stock'] = array_sum(array_column($skuPricesArray, 'stock')); // 根据配置决定是否显示销量 if ($showSales != 1) { unset($goods['sales']); } } else { $goods['stock'] = 0; $goods['sales'] = 0; } } return $goods; } /** * 默认调用 query 中的方法,比如 withTrashed() * * @param string $funcname * @param array $arguments * @return self */ public function __call($funcname, $arguments) { $this->query->{$funcname}(...$arguments); return $this; } }