vr-shopxo-plugin/shopxo/app/service/SearchService.php

1246 lines
44 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
// +----------------------------------------------------------------------
// | ShopXO 国内领先企业级B2C免费开源电商系统
// +----------------------------------------------------------------------
// | Copyright (c) 2011~2099 http://shopxo.net All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://opensource.org/licenses/mit-license.php )
// +----------------------------------------------------------------------
// | Author: Devil
// +----------------------------------------------------------------------
namespace app\service;
use think\facade\Db;
use app\service\SystemService;
use app\service\GoodsService;
use app\service\BrandService;
use app\service\ResourcesService;
use app\service\GoodsCategoryService;
use app\service\RegionService;
/**
* 搜索服务层
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2016-12-01T21:51:08+0800
*/
class SearchService
{
/**
* 数据列表处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2026-01-19
* @desc description
* @param [array] $data [数据列表]
* @param [array] $params [输入参数]
*/
public static function DataHandle($data, $params = [])
{
if(!empty($data))
{
// 品牌
$brand = BrandService::BrandName(array_unique(call_user_func_array('array_merge', array_filter(array_map(function($item)
{
return empty($item['brand_ids']) ? '' : json_decode($item['brand_ids'], true);
}, $data)))));
// 商品分类
$category = GoodsCategoryService::GoodsCategoryName(array_unique(call_user_func_array('array_merge', array_filter(array_map(function($item)
{
return empty($item['category_ids']) ? '' : json_decode($item['category_ids'], true);
}, $data)))));
// 产地
$produce_region = RegionService::RegionName(array_unique(call_user_func_array('array_merge', array_filter(array_map(function($item)
{
return empty($item['produce_region_ids']) ? '' : json_decode($item['produce_region_ids'], true);
}, $data)))));
foreach($data as &$v)
{
// 品牌
if(array_key_exists('brand_ids', $v))
{
$brand_arr = [];
if(!empty($brand) && !empty($v['brand_ids']))
{
$brand_ids = json_decode($v['brand_ids'], true);
foreach($brand_ids as $tv)
{
if(array_key_exists($tv, $brand))
{
$brand_arr[] = $brand[$tv];
}
}
}
$v['brand_text'] = empty($brand_arr) ? '' : implode('', $brand_arr);
}
// 商品分类
if(array_key_exists('category_ids', $v))
{
$category_arr = [];
if(!empty($category) && !empty($v['category_ids']))
{
$category_ids = json_decode($v['category_ids'], true);
foreach($category_ids as $tv)
{
if(array_key_exists($tv, $category))
{
$category_arr[] = $category[$tv];
}
}
}
$v['category_text'] = empty($category_arr) ? '' : implode('', $category_arr);
}
// 价格范围
if(array_key_exists('screening_price_values', $v))
{
$v['screening_price_values'] = empty($v['screening_price_values']) ? '' : implode('', json_decode($v['screening_price_values'], true));
}
// 产地
if(array_key_exists('produce_region_ids', $v))
{
$produce_region_arr = [];
if(!empty($produce_region) && !empty($v['produce_region_ids']))
{
$produce_region_ids = json_decode($v['produce_region_ids'], true);
foreach($produce_region_ids as $tv)
{
if(array_key_exists($tv, $produce_region))
{
$produce_region_arr[] = $produce_region[$tv];
}
}
}
$v['produce_region_text'] = empty($produce_region_arr) ? '' : implode('', $produce_region_arr);
}
// 商品参数
if(array_key_exists('goods_params_values', $v))
{
$v['goods_params_values'] = empty($v['goods_params_values']) ? '' : implode('', json_decode($v['goods_params_values'], true));
}
// 商品规格
if(array_key_exists('goods_spec_values', $v))
{
$v['goods_spec_values'] = empty($v['goods_spec_values']) ? '' : implode('', json_decode($v['goods_spec_values'], true));
}
}
}
return $data;
}
/**
* 排序列表
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-11-01
* @desc description
* @param [array] $params [输入参数]
*/
public static function SearchMapOrderByList($params = [])
{
// 移除分页和框架的s模块参数
unset($params['page'], $params['s']);
// 处理排序参数
$ov = empty($params['ov']) ? ['default'] : explode('-', $params['ov']);
$data = MyConst('common_search_order_by_list');
foreach($data as &$v)
{
// 是否选中
$v['is_active'] = ($ov[0] == $v['type']) ? 1 : 0;
// url
$temp_ov = '';
if($v['type'] == 'default')
{
$temp_params = $params;
unset($temp_params['ov']);
} else {
// 类型
if($ov[0] == $v['type'])
{
$v['value'] = ($ov[1] == 'desc') ? 'asc' : 'desc';
}
// 参数值
$temp_ov = $v['type'].'-'.$v['value'];
$temp_params = array_merge($params, ['ov'=>$temp_ov]);
}
$v['url'] = MyUrl('index/search/index', $temp_params);
}
return $data;
}
/**
* 搜素条件处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-06-30
* @desc description
* @param [array] $data [数据列表]
* @param [string] $pid [参数字段]
* @param [string] $did [数据字段]
* @param [array] $params [输入参数]
* @param [array] $ext [扩展数据]
*/
public static function SearchMapHandle($data, $pid, $did, $params, $ext = [])
{
// 移除分页和框架的s模块参数
unset($params['page'], $params['s']);
// ascii字段处理
$is_ascii = isset($ext['is_ascii']) && $ext['is_ascii'] == true;
$field = empty($ext['field']) ? 'value' : $ext['field'];
foreach($data as &$v)
{
// 是否转ascii处理主键字段
if($is_ascii && !empty($field) && isset($v[$field]))
{
$v[$did] = StrToAscii($v[$field]);
}
$temp_params = $params;
if(isset($v[$did]))
{
if(isset($params[$pid]) && $params[$pid] == $v[$did])
{
unset($temp_params[$pid]);
} else {
$temp_params = array_merge($params, [$pid=>$v[$did]]);
}
}
$v['url'] = MyUrl('index/search/index', $temp_params);
$v['is_active'] = (isset($params[$pid]) && isset($v[$did]) && $params[$pid] == $v[$did]) ? 1 : 0;
}
return $data;
}
/**
* 获取商品列表
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-09-07
* @desc description
* @param [array] $map [搜素条件]
* @param [array] $params [输入参数]
*/
public static function GoodsList($map, $params = [])
{
// 返回格式
$result = [
'page_start' => 0,
'page_size' => 0,
'page' => 1,
'page_total' => 0,
'total' => 0,
'data' => [],
];
// 搜索条件
$order_by = $map['order_by'];
$where_base = $map['base'];
$where_keywords = $map['keywords'];
$where_screening_price = $map['screening_price'];
// 分页计算
$field = 'g.*';
$result['page'] = max(1, isset($params['page']) ? intval($params['page']) : 1);
$result['page_size'] = empty($params['page_size']) ? MyC('home_search_limit_number', 20, true) : intval($params['page_size']);
// 数量不能超过500
if($result['page_size'] > 500)
{
$result['page_size'] = 500;
}
$result['page_start'] = intval(($result['page']-1)*$result['page_size']);
// 搜索商品列表读取前钩子
$hook_name = 'plugins_service_search_goods_list_begin';
MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => &$params,
'where_base' => &$where_base,
'where_keywords' => &$where_keywords,
'where_screening_price' => &$where_screening_price,
'field' => &$field,
'order_by' => &$order_by,
'page' => &$result['page'],
'page_start' => &$result['page_start'],
'page_size' => &$result['page_size'],
]);
// 获取商品总数
$result['total'] = (int) Db::name('Goods')->alias('g')->join('goods_category_join gci', 'g.id=gci.goods_id')->where($where_base)->where(function($query) use($where_keywords) {
self::SearchKeywordsWhereJoinType($query, $where_keywords);
})->where(function($query) use($where_screening_price) {
$query->whereOr($where_screening_price);
})->count('DISTINCT g.id');
// 获取商品列表
if($result['total'] > 0)
{
// 查询数据
$data = Db::name('Goods')->alias('g')->join('goods_category_join gci', 'g.id=gci.goods_id')->field($field)->where($where_base)->where(function($query) use($where_keywords) {
self::SearchKeywordsWhereJoinType($query, $where_keywords);
})->where(function($query) use($where_screening_price) {
$query->whereOr($where_screening_price);
})->group('g.id')->order($order_by)->limit($result['page_start'], $result['page_size'])->select()->toArray();
// 数据处理
$params['is_spec'] = (!isset($params['is_spec']) || $params['is_spec'] == 1) ? 1 : 0;
$params['is_cart'] = (!isset($params['is_cart']) || $params['is_cart'] == 1) ? 1 : 0;
$goods = GoodsService::GoodsDataHandle($data, $params);
// 返回数据
$result['data'] = $goods['data'];
$result['page_total'] = ceil($result['total']/$result['page_size']);
} else {
return DataReturn(MyLang('no_data'), -1, $result);
}
return DataReturn(MyLang('handle_success'), 0, $result);
}
/**
* 关键字搜索关系类型
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-04-02
* @desc description
* @param [object] $query [查询对象]
* @param [array] $where_keywords [搜索关键字]
*/
public static function SearchKeywordsWhereJoinType($query, $where_keywords)
{
// 搜索关键字默认或的关系
$join = 'whereOr';
// 是否开启并且关系
if(MyC('home_search_is_keywords_where_and') == 1)
{
$join = 'where';
}
// 条件设置
$query->$join($where_keywords);
}
/**
* 搜索条件处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-01-08
* @desc description
* @param [array] $params [输入参数]
*/
public static function SearchWhereHandle($params = [])
{
// 搜索商品条件处理钩子
$hook_name = 'plugins_service_search_goods_list_where';
MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => &$params,
]);
// 基础条件
$where_base = [
['g.is_delete_time', '=', 0],
['g.is_shelves', '=', 1]
];
// 关键字
$where_keywords = [];
if(!empty($params['wd']))
{
// WEB端则处理关键字
if(APPLICATION_CLIENT_TYPE == 'pc')
{
$params['wd'] = AsciiToStr($params['wd']);
}
$keywords = explode(' ', str_replace('+', ' ', trim($params['wd'])));
$is_keywords_spec = true;
if(count($keywords) == 1)
{
$goods_ids = Db::name('GoodsSpecBase')->where(['barcode|coding'=>$keywords[0]])->column('goods_id');
if(!empty($goods_ids))
{
$where_base[] = ['g.id', 'in', $goods_ids];
$is_keywords_spec = false;
}
}
if($is_keywords_spec)
{
$keywords_fields = 'g.title|g.simple_desc|g.spec_desc|g.approval_number|g.batch_number|g.produce_company|g.coding|g.model';
if(MyC('home_search_is_keywords_seo_fields') == 1)
{
$keywords_fields .= '|g.seo_title|g.seo_keywords|g.seo_desc';
}
foreach($keywords as $kv)
{
$where_keywords[] = [$keywords_fields, 'like', '%'.$kv.'%'];
}
}
}
// 品牌
// 不存在搜索品牌的时候则看是否指定品牌
if(!empty($params['brand_ids']))
{
if(!is_array($params['brand_ids']))
{
$params['brand_ids'] = (substr($params['brand_ids'], 0, 1) == '{') ? json_decode(htmlspecialchars_decode($params['brand_ids']), true) : explode(',', $params['brand_ids']);
}
if(!empty($params['brand_ids']))
{
$where_base[] = ['g.brand_id', 'in', array_unique($params['brand_ids'])];
}
}
// 指定品牌
if(!empty($params['brand']))
{
$where_base[] = ['g.brand_id', 'in', [intval($params['brand'])]];
}
// web端
if(!empty($params['bid']))
{
$where_base[] = ['g.brand_id', 'in', [intval($params['bid'])]];
}
// 分类id
// 不存在搜索分类的时候则看是否指定分类
if(!empty($params['category_ids']))
{
if(!is_array($params['category_ids']))
{
$params['category_ids'] = (substr($params['category_ids'], 0, 1) == '{') ? json_decode(htmlspecialchars_decode($params['category_ids']), true) : explode(',', $params['category_ids']);
}
if(!empty($params['category_ids']))
{
$ids = GoodsCategoryService::GoodsCategoryItemsIds($params['category_ids'], 1);
$where_base[] = ['gci.category_id', 'in', $ids];
}
} else {
if(!empty($params['category_id']))
{
$ids = GoodsCategoryService::GoodsCategoryItemsIds([intval($params['category_id'])], 1);
$where_base[] = ['gci.category_id', 'in', $ids];
}
}
// web端
if(!empty($params['cid']))
{
$ids = GoodsCategoryService::GoodsCategoryItemsIds([intval($params['cid'])], 1);
$where_base[] = ['gci.category_id', 'in', $ids];
}
// 产地、单个id
if(!empty($params['poid']))
{
$where_base[] = ['g.produce_region', '=', intval($params['poid'])];
}
// 产地、多个id
if(!empty($params['produce_region_ids']))
{
if(!is_array($params['produce_region_ids']))
{
$params['produce_region_ids'] = (substr($params['produce_region_ids'], 0, 1) == '{') ? json_decode(htmlspecialchars_decode($params['produce_region_ids']), true) : explode(',', $params['produce_region_ids']);
}
if(!empty($params['produce_region_ids']))
{
$where_base[] = ['g.produce_region', 'in', $params['produce_region_ids']];
}
}
// 筛选价格
$map_price = [];
$where_screening_price = [];
if(!empty($params['screening_price_values']))
{
if(!is_array($params['screening_price_values']))
{
$map_price = (substr($params['screening_price_values'], 0, 1) == '{') ? json_decode(htmlspecialchars_decode($params['screening_price_values']), true) : explode(',', $params['screening_price_values']);
}
}
// web端
if(!empty($params['peid']))
{
$temp_price = Db::name('ScreeningPrice')->where(['is_enable'=>1, 'id'=>intval($params['peid'])])->field('min_price,max_price')->find();
if(!empty($temp_price))
{
$map_price[] = implode('-', $temp_price);
}
}
// 价格滑条
if(!empty($params['price']) && stripos($params['price'], '-') !== false)
{
$map_price[] = $params['price'];
}
// 处理价格条件
if(!empty($map_price))
{
foreach($map_price as $v)
{
$temp = explode('-', $v);
if(count($temp) == 2)
{
// 最小金额等于0、最大金额大于0
if(empty($temp[0]) && !empty($temp[1]))
{
$where_screening_price[] = [
['min_price', '<=', $temp[1]],
];
// 最小金额大于0、最大金额大于0
// 最小金额等于0、最大金额等于0
} elseif((!empty($temp[0]) && !empty($temp[1])) || (empty($temp[0]) && empty($temp[1])))
{
$where_screening_price[] = [
['min_price', '>=', $temp[0]],
['min_price', '<=', $temp[1]],
];
// 最小金额大于0、最大金额等于0
} elseif(!empty($temp[0]) && empty($temp[1]))
{
$where_screening_price[] = [
['min_price', '>=', $temp[0]],
];
}
}
}
}
// 商品参数、属性
$map_params = [];
if(!empty($params['goods_params_values']))
{
if(!is_array($params['goods_params_values']))
{
$map_params = (substr($params['goods_params_values'], 0, 1) == '{') ? json_decode(htmlspecialchars_decode($params['goods_params_values']), true) : explode(',', $params['goods_params_values']);
}
}
if(!empty($params['psid']))
{
$map_params[] = AsciiToStr($params['psid']);
}
if(!empty($map_params))
{
$map_params = array_map(function($item)
{
return md5($item);
}, $map_params);
$ids = Db::name('GoodsParams')->where(['md5_key'=>$map_params, 'scope'=>self::SearchParamsWhereTypeValue()])->column('goods_id');
if(!empty($ids))
{
$where_base[] = ['g.id', 'in', $ids];
}
}
// 商品规格
$map_spec = [];
if(!empty($params['goods_spec_values']))
{
if(!is_array($params['goods_spec_values']))
{
$map_spec = (substr($params['goods_spec_values'], 0, 1) == '{') ? json_decode(htmlspecialchars_decode($params['goods_spec_values']), true) : explode(',', $params['goods_spec_values']);
}
}
if(!empty($params['scid']))
{
$map_spec[] = AsciiToStr($params['scid']);
}
if(!empty($map_spec))
{
$map_spec = array_map(function($item)
{
return md5($item);
}, $map_spec);
$ids = Db::name('GoodsSpecValue')->where(['md5_key'=>$map_spec])->column('goods_id');
if(!empty($ids))
{
$where_base[] = ['g.id', 'in', $ids];
}
}
// 排序
$order_by = 'g.sort_level desc, g.access_count desc, g.sales_count desc, g.id desc';
if(!empty($params['ov']))
{
// 数据库字段映射关系
$fields = [
'sales' => 'g.sales_count',
'access' => 'g.access_count',
'price' => 'g.min_price',
'new' => 'g.id',
];
// 参数判断
$temp = explode('-', $params['ov']);
if(count($temp) == 2 && $temp[0] != 'default' && array_key_exists($temp[0], $fields) && in_array($temp[1], ['desc', 'asc']))
{
$order_by = $fields[$temp[0]].' '.$temp[1];
}
} else {
if(!empty($params['order_by_type']) && !empty($params['order_by_field']) && $params['order_by_field'] != 'default')
{
$order_by = 'g.'.$params['order_by_field'].' '.$params['order_by_type'];
}
}
// 是否存在搜索条件
$is_map = (count($where_base) > 2 || !empty($where_keywords) || !empty($where_screening_price) || !empty($params['ov'])) ? 1 : 0;
return [
'base' => $where_base,
'keywords' => $where_keywords,
'screening_price' => $where_screening_price,
'order_by' => $order_by,
'is_map' => $is_map,
];
}
/**
* 参数搜索条件类型
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-04-11
* @desc description
*/
public static function SearchParamsWhereTypeValue()
{
// 获取配置
$value = MyC('home_search_params_type');
if(empty($value))
{
$value = [2];
}
// 是否为数组
if(!is_array($value))
{
$value = explode(',', $value);
}
return $value;
}
/**
* 搜索记录添加
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2018-10-21T00:37:44+0800
* @param [array] $params [输入参数]
*/
public static function SearchAdd($params = [])
{
// 是否增加搜索记录
if(MyC('home_search_history_record', 0) == 1)
{
// 排序
$ov_arr = empty($params['ov']) ? '' : explode('-', $params['ov']);
if(empty($ov_arr) && !empty($params['order_by_type']) && !empty($params['order_by_field']))
{
$ov_arr = [$params['order_by_field'], $params['order_by_type']];
}
// 结果仅保留商品id
if(!empty($params['search_result_data']) && is_array($params['search_result_data']) && !empty($params['search_result_data']['data']))
{
$params['search_result_data']['data'] = array_column($params['search_result_data']['data'], 'id');
}
// 日志数据
$data = [
'user_id' => isset($params['user_id']) ? intval($params['user_id']) : 0,
'keywords' => empty($params['wd']) ? '' : $params['wd'],
'order_by_field' => empty($ov_arr) ? '' : $ov_arr[0],
'order_by_type' => empty($ov_arr) ? '' : $ov_arr[1],
'search_result' => empty($params['search_result_data']) ? '' : (is_array($params['search_result_data']) ? json_encode($params['search_result_data'], JSON_UNESCAPED_UNICODE) : $params['search_result_data']),
'ip' => GetClientIP(),
'ymd' => date('Ymd'),
'add_time' => time(),
];
// 参数处理
$field_arr = [
'brand_ids' => ['brand_ids', 'brand', 'bid'],
'category_ids' => ['category_ids', 'category_id', 'cid'],
'screening_price_values' => ['screening_price_values', 'peid'],
'goods_params_values' => ['goods_params_values', 'psid'],
'goods_spec_values' => ['goods_spec_values', 'scid'],
'produce_region_ids' => ['produce_region_ids', 'poid'],
];
foreach($field_arr as $k=>$v)
{
$item = [];
foreach($v as $vs)
{
if(!empty($params[$vs]))
{
// 价格区间
if($vs == 'peid')
{
$temp_price = Db::name('ScreeningPrice')->where(['is_enable'=>1, 'id'=>intval($params[$vs])])->field('min_price,max_price')->find();
$params[$vs] = empty($temp_price) ? '' : implode('-', $temp_price);
}
// Ascii处理
if(in_array($vs, ['psid', 'scid']))
{
$params[$vs] = AsciiToStr($params[$vs]);
}
// 合并参数
$tv = (substr($params[$vs], 0, 1) == '{') ? json_decode(htmlspecialchars_decode($params[$vs]), true) : $params[$vs];
if($tv !== '' && $tv !== null)
{
$item = array_merge($item, is_array($tv) ? $tv : [$tv]);
}
}
}
$data[$k] = empty($item) ? '' : (is_array($item) ? json_encode($item, JSON_UNESCAPED_UNICODE) : $item);
}
Db::name('SearchHistory')->insert($data);
}
}
/**
* 搜索关键字列表
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-01-03
* @desc description
* @param [array] $params [输入参数]
*/
public static function SearchKeywordsList($params = [])
{
$key = SystemService::CacheKey('shopxo.cache_search_keywords_key');
$data = MyCache($key);
if($data === null || MyEnv('app_debug'))
{
switch(intval(MyC('home_search_keywords_type', 0)))
{
case 1 :
$data = Db::name('SearchHistory')->where([['keywords', '<>', '']])->group('keywords')->limit(10)->column('keywords');
break;
case 2 :
$keywords = MyC('home_search_keywords', '', true);
if(!empty($keywords))
{
$data = explode(',', $keywords);
}
break;
}
// 没数据则赋空数组值
if(empty($data))
{
$data = [];
}
// 存储缓存
MyCache($key, $data, 180);
}
return $data;
}
/**
* 分类下品牌列表
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-08-29
* @desc description
* @param [array] $map [搜索条件]
* @param [array] $params [输入参数]
*/
public static function CategoryBrandList($map, $params = [])
{
$data = [];
if(MyC('home_search_is_brand', 0) == 1)
{
// 基础条件
$brand_where = [
['is_enable', '=', 1],
];
// 仅搜索关键字相关的品牌
if(!empty($map['keywords']))
{
$where_keywords = $map['keywords'];
$ids = Db::name('Goods')->alias('g')->join('goods_category_join gci', 'g.id=gci.goods_id')->where(function($query) use($where_keywords) {
self::SearchKeywordsWhereJoinType($query, $where_keywords);
})->group('g.brand_id')->column('g.brand_id');
if(!empty($ids))
{
$brand_where[] = ['id', 'in', array_unique($ids)];
}
}
// 仅获取已关联商品的品牌
$where = [
['is_shelves', '=', 1],
['is_delete_time', '=', 0],
['brand_id', '>', 0],
];
$ids = Db::name('Goods')->where($where)->column('distinct brand_id');
if(!empty($ids))
{
$brand_where[] = ['id', 'in', $ids];
}
// 获取品牌列表
$data_params = [
'field' => 'id,name,logo,website_url',
'where' => $brand_where,
'm' => 0,
'n' => 0,
];
$ret = BrandService::BrandList($data_params);
$data = empty($ret['data']) ? [] : $ret['data'];
}
return $data;
}
/**
* 根据分类id获取下级列表
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-08-29
* @desc description
* @param [array] $params [输入参数]
*/
public static function GoodsCategoryList($params = [])
{
$data = [];
if(MyC('home_search_is_category', 0) == 1)
{
$cid = empty($params['category_id']) ? (empty($params['cid']) ? 0 : intval($params['cid'])) : intval($params['category_id']);
$where = [
['pid', '=', intval($cid)],
];
$data = GoodsCategoryService::GoodsCategoryList(['where'=>$where, 'field'=>'id,name']);
}
return $data;
}
/**
* 获取商品价格筛选列表
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-09-07
* @desc description
* @param [array] $params [输入参数]
*/
public static function ScreeningPriceList($params = [])
{
$data = [];
if(MyC('home_search_is_price', 0) == 1)
{
$data = Db::name('ScreeningPrice')->field('id,name,min_price,max_price')->where(['is_enable'=>1])->order('sort asc')->select()->toArray();
}
return $data;
}
/**
* 搜索商品产地、去重
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-01-08
* @desc description
* @param [array] $map [搜素条件]
* @param [array] $params [输入参数]
*/
public static function SearchGoodsProduceRegionList($map, $params = [])
{
$data = [];
if(MyC('home_search_is_produce_region', 0) == 1)
{
// 搜索条件
$where_base = $map['base'];
$where_keywords = $map['keywords'];
$where_screening_price = $map['screening_price'];
// 一维数组、参数值去重
$list = RegionService::RegionName(Db::name('Goods')->alias('g')->join('goods_category_join gci', 'g.id=gci.goods_id')->join('goods_params gp', 'g.id=gp.goods_id')->where($where_base)->where(function($query) use($where_keywords) {
self::SearchKeywordsWhereJoinType($query, $where_keywords);
})->where(function($query) use($where_screening_price) {
$query->whereOr($where_screening_price);
})->group('g.produce_region')->column('g.produce_region'));
if(!empty($list))
{
foreach($list as $k=>$v)
{
$data[] = [
'id' => $k,
'name' => $v,
];
}
}
}
return $data;
}
/**
* 搜索商品参数列表、去重
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-01-08
* @desc description
* @param [array] $map [搜素条件]
* @param [array] $params [输入参数]
*/
public static function SearchGoodsParamsValueList($map, $params = [])
{
$data = [];
if(MyC('home_search_is_params', 0) == 1)
{
// 搜索条件
$where_base = $map['base'];
$where_keywords = $map['keywords'];
$where_screening_price = $map['screening_price'];
// 仅搜索基础参数
$where_base[] = ['gp.scope', 'in', self::SearchParamsWhereTypeValue()];
// 一维数组、参数值去重
$data = Db::name('Goods')->alias('g')->join('goods_category_join gci', 'g.id=gci.goods_id')->join('goods_params gp', 'g.id=gp.goods_id')->where($where_base)->where(function($query) use($where_keywords) {
self::SearchKeywordsWhereJoinType($query, $where_keywords);
})->where(function($query) use($where_screening_price) {
$query->whereOr($where_screening_price);
})->group('gp.value')->field('gp.value')->select()->toArray();
}
return $data;
}
/**
* 搜索商品规格列表、去重
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-01-08
* @desc description
* @param [array] $map [搜素条件]
* @param [array] $params [输入参数]
*/
public static function SearchGoodsSpecValueList($map, $params = [])
{
$data = [];
if(MyC('home_search_is_spec', 0) == 1)
{
// 搜索条件
$where_base = $map['base'];
$where_keywords = $map['keywords'];
$where_screening_price = $map['screening_price'];
// 一维数组、参数值去重
$data = Db::name('Goods')->alias('g')->join('goods_category_join gci', 'g.id=gci.goods_id')->join('goods_spec_value gsv', 'g.id=gsv.goods_id')->where($where_base)->where(function($query) use($where_keywords) {
self::SearchKeywordsWhereJoinType($query, $where_keywords);
})->where(function($query) use($where_screening_price) {
$query->whereOr($where_screening_price);
})->group('gsv.value')->field('gsv.value')->select()->toArray();
}
return $data;
}
/**
* 搜索条件基础数据
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-01-11
* @desc description
* @param [array] $params [输入参数]
*/
public static function SearchMapInfo($params = [])
{
// 分类
$category = null;
$cid = empty($params['category_id']) ? (empty($params['cid']) ? 0 : intval($params['cid'])) : intval($params['category_id']);
if(!empty($cid))
{
$category = GoodsCategoryService::GoodsCategoryRow(['id'=>$cid, 'field'=>'name,vice_name,describe,seo_title,seo_keywords,seo_desc']);
}
// 品牌
$brand = null;
$bid = empty($params['brand']) ? (empty($params['bid']) ? 0 : intval($params['bid'])) : intval($params['brand']);
if(!empty($bid))
{
$data_params = [
'field' => 'id,name,describe,logo,website_url,seo_title,seo_keywords,seo_desc',
'where' => [
['id', '=', $bid]
],
'm' => 0,
'n' => 1,
];
$ret = BrandService::BrandList($data_params);
if(!empty($ret['data']) && !empty($ret['data'][0]))
{
$brand = $ret['data'][0];
}
}
return [
'category' => empty($category) ? null : $category,
'brand' => empty($brand) ? null : $brand,
];
}
/**
* 搜索商品最大金额
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2024-04-21
* @desc description
* @param [array] $params [输入参数]
*/
public static function SearchGoodsMaxPrice($params = [])
{
return Db::name('GoodsSpecBase')->max('price');
}
/**
* 搜索禁止
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2024-06-19
* @desc description
* @param [array] $params [输入参数]
*/
public static function SearchProhibitCheck($params = [])
{
// 用户UserAgent禁止验证
if(!empty($_SERVER) && !empty($_SERVER['HTTP_USER_AGENT']))
{
$prohibit = MyC('home_search_prohibit_user_agent', '', true);
if(!empty($prohibit))
{
$user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
$prohibit = explode(',', strtolower($prohibit));
foreach($prohibit as $v)
{
if(stripos($user_agent, $v) !== false)
{
return DataReturn(MyLang('illegal_access_tips').'('.$v.')', -1);
}
}
}
}
// 禁止关键字
if(!empty($params['wd']))
{
$prohibit = MyC('home_search_prohibit_keywords', [], true);
if(!empty($prohibit) && is_array($prohibit) && in_array($params['wd'], $prohibit))
{
return DataReturn(MyLang('illegal_access_tips').'('.$params['wd'].')', -1);
}
}
return DataReturn('success', 0);
}
/**
* 搜索是否需要登录
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2024-06-19
* @desc description
* @param [array] $params [输入参数]
*/
public static function SearchIsLoginCheck($params = [])
{
$data = MyC('home_search_is_login_required', [], true);
if(empty($data) || !is_array($data) || !in_array(APPLICATION_CLIENT_TYPE, $data))
{
return DataReturn('success', 0);
}
return DataReturn('error', -1);
}
/**
* 搜索排行榜
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2024-10-14
* @desc description
* @param [array] $params [输入参数]
*/
public static function SearchRankingList($params = [])
{
$key = SystemService::CacheKey('shopxo.cache_search_start_ranking_key').APPLICATION_CLIENT_TYPE;
$data = MyCache($key);
if($data === null || MyEnv('app_debug'))
{
// 数据缓存
$data = [];
// 销量
$where = [
['is_shelves', '=', 1],
['is_delete_time', '=', 0],
['inventory', '>', 0],
];
$field = 'id,title,images';
$goods = Db::name('Goods')->where($where)->field($field)->order('sales_count desc')->limit(0, 10)->select()->toArray();
if(!empty($goods))
{
$data[] = [
'name' => MyLang('sales_title'),
'icon' => 'icon-fire',
'data' => $goods
];
}
// 评分
$where = [
['g.is_shelves', '=', 1],
['g.is_delete_time', '=', 0],
['g.inventory', '>', 0],
['gc.business_type', '=', 'order'],
];
$field = 'g.id,g.title,g.images,AVG(gc.rating) AS avg_rating';
$goods = Db::name('GoodsComments')->alias('gc')->join('goods g', 'g.id=gc.goods_id')->where($where)->field($field)->order('avg_rating desc')->group('g.id')->limit(0, 10)->select()->toArray();
if(!empty($goods))
{
$data[] = [
'name' => MyLang('score_title'),
'icon' => 'icon-fire',
'data' => $goods
];
}
// 收藏
$where = [
['g.is_shelves', '=', 1],
['g.is_delete_time', '=', 0],
['g.inventory', '>', 0],
];
$field = 'g.id,g.title,g.images,COUNT(g.id) AS count';
$goods = Db::name('GoodsFavor')->alias('gf')->join('goods g', 'g.id=gf.goods_id')->where($where)->field($field)->order('count desc')->group('g.id')->limit(0, 10)->select()->toArray();
if(!empty($goods))
{
$data[] = [
'name' => MyLang('favor_title'),
'icon' => 'icon-fire',
'data' => $goods
];
}
// 数据处理
if(!empty($data))
{
foreach($data as &$v)
{
if(!empty($v['data']))
{
foreach($v['data'] as &$vs)
{
$vs['goods_url'] = GoodsService::GoodsUrlCreate($vs['id']);
$vs['images'] = ResourcesService::AttachmentPathViewHandle($vs['images']);
}
}
}
}
// 存储缓存
MyCache($key, $data, 180);
}
return $data;
}
/**
* 搜索开始数据
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2024-10-14
* @desc description
* @param [array] $params [输入参数]
*/
public static function SearchStartData($params = [])
{
return DataReturn('success', 0, [
// 推荐关键字
'search_keywords' => self::SearchKeywordsList($params),
// 排行
'ranking_list' => self::SearchRankingList($params),
]);
}
/**
* 删除
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-11-18
* @desc description
* @param [array] $params [输入参数]
*/
public static function SearchHistoryDelete($params = [])
{
// 参数是否有误
if(empty($params['ids']))
{
return DataReturn(MyLang('data_id_error_tips'), -1);
}
// 是否数组
if(!is_array($params['ids']))
{
$params['ids'] = explode(',', $params['ids']);
}
// 删除操作
if(Db::name('SearchHistory')->where(['id'=>$params['ids']])->delete())
{
return DataReturn(MyLang('delete_success'), 0);
}
return DataReturn(MyLang('delete_fail'), -100);
}
/**
* 清空全部
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-11-18
* @desc description
* @param [array] $params [输入参数]
*/
public static function SearchHistoryAllDelete($params = [])
{
$where = [
['id', '>', 0]
];
if(Db::name('SearchHistory')->where($where)->delete() === false)
{
return DataReturn(MyLang('operate_fail'), -100);
}
return DataReturn(MyLang('operate_success'));
}
}
?>