|
|
@@ -73,7 +73,7 @@ class FeatureService
|
|
|
foreach ($m as $string){
|
|
|
if (is_numeric($string)){//填入特征信息
|
|
|
if (isset($featureMap[$string])){
|
|
|
- $arr["type"] = Feature::type[$features[$featureMap[$string]]->type];
|
|
|
+ $arr["type"] = Feature::TYPE[$features[$featureMap[$string]]->type];
|
|
|
$arr["id"] = $features[$featureMap[$string]]->id;
|
|
|
$arr["logic"] = $features[$featureMap[$string]]->logic;
|
|
|
$arr["describe"] = $features[$featureMap[$string]]->describe;
|
|
|
@@ -128,7 +128,7 @@ class FeatureService
|
|
|
$map = [];
|
|
|
foreach ($features as &$feature){
|
|
|
if (!$feature["type"] || !$feature["logic"] || !$feature["describe"])continue;
|
|
|
- $typeMap = array_flip(Feature::type);
|
|
|
+ $typeMap = array_flip(Feature::TYPE);
|
|
|
$f = Feature::query()->firstOrCreate([
|
|
|
"type"=>$typeMap[$feature["type"]], //特征类型
|
|
|
"logic"=>$feature["logic"], //特征逻辑
|
|
|
@@ -163,7 +163,7 @@ class FeatureService
|
|
|
preg_match_all('/\d+|[\&\|\(\)]/',$value,$result);
|
|
|
foreach ($result[0] as &$str){
|
|
|
if (is_numeric($str) && isset($features[$str])){
|
|
|
- $column = Feature::type[$features[$str]["type"]];
|
|
|
+ $column = Feature::TYPE[$features[$str]["type"]];
|
|
|
$logic = $features[$str]["logic"];
|
|
|
$describe = $features[$str]["describe"];
|
|
|
if ($columnMapping){
|
|
|
@@ -209,106 +209,96 @@ class FeatureService
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 匹配特征
|
|
|
- * $vale : 特征简述 例: "1&2|(3|4)"
|
|
|
- * $columnMapping : 列映射 例:["商品名称"=>"commodity_name"]
|
|
|
- * $matchObject : 被匹配对象,必须存在列映射所指定字段 例:["commodity_name"=>"衣服"]
|
|
|
- * $isMultiMatching 是否开启多重匹配 开启将匹配对象视为二维数组深层寻找商品(入库需要)
|
|
|
- * bool true匹配成功 false匹配失败
|
|
|
+ * 匹配特征 true匹配成功 false匹配失败
|
|
|
*
|
|
|
* @param string $value
|
|
|
* @param array $columnMapping
|
|
|
* @param array $matchObject
|
|
|
- * @param bool $isMultiMatching
|
|
|
+ *
|
|
|
* @return bool
|
|
|
*/
|
|
|
- public function matchFeature($value, $columnMapping, $matchObject, $isMultiMatching = false) :bool
|
|
|
+ public function matchFeature($value, $columnMapping, $matchObject) :bool
|
|
|
{
|
|
|
if (!$value)return true;
|
|
|
|
|
|
preg_match_all('/\d+|[\&\|\(\)]/',$value,$result);
|
|
|
if (implode("",$result[0]) != $value)return false;
|
|
|
|
|
|
- $features = app(CacheService::class)->getOrExecute($value,function ()use($value){
|
|
|
+ foreach ($result[0] as &$str) {
|
|
|
+ switch ($str){
|
|
|
+ case "&":
|
|
|
+ $str = "&&";
|
|
|
+ break;
|
|
|
+ case "|":
|
|
|
+ $str = "||";
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ $str = $this->match($str, $value, $columnMapping, $matchObject);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $is = implode("",$result[0]);
|
|
|
+ return eval("return $is;");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 匹配实例
|
|
|
+ *
|
|
|
+ * @param string|integer $id
|
|
|
+ * @param string $value
|
|
|
+ * @param array $columnMapping
|
|
|
+ * @param array $matchObject
|
|
|
+ *
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ private function match($id, $value, $columnMapping, $matchObject):string
|
|
|
+ {
|
|
|
+ if (!is_numeric($id))return $id; //非特征返回本身
|
|
|
+
|
|
|
+ $features = app(CacheService::class)->getOrExecute("feature:".$value,function ()use($value){
|
|
|
preg_match_all('/\d+/',$value,$ids);
|
|
|
if ($ids[0])$fs = Feature::query()->whereIn("id",$ids[0])->get();
|
|
|
else return false;
|
|
|
$features = [];
|
|
|
- foreach ($fs as $f){
|
|
|
- $features[$f->id] = $f;
|
|
|
- }
|
|
|
+ foreach ($fs as $f)$features[$f->id] = $f;
|
|
|
return $features;
|
|
|
});
|
|
|
|
|
|
- foreach ($result[0] as &$str) {
|
|
|
- if (is_numeric($str) && isset($features[$str])) {
|
|
|
- $column = Feature::type[$features[$str]["type"]];
|
|
|
- $logic = $features[$str]["logic"];
|
|
|
- $describe = $features[$str]["describe"];
|
|
|
- if (($column == '商品名称' || $column == '商品备注' || $column == '长') && $isMultiMatching){
|
|
|
- $packageColumn = $columnMapping["packages"] ?? "packages";
|
|
|
- $packages = $matchObject[$packageColumn] ?? [];
|
|
|
- $str = $this->multiMatching($packages,$logic,$describe,$columnMapping[$column] ?? '');
|
|
|
- continue;
|
|
|
- }
|
|
|
- $value = isset($columnMapping[$column]) ? ($matchObject[$columnMapping[$column]] ?? '') : '';
|
|
|
- switch ($logic) {
|
|
|
- case "包含":
|
|
|
- $str = mb_strpos($value,$describe) === false ? 'false' : 'true';
|
|
|
- break;
|
|
|
- case "不包含":
|
|
|
- $str = mb_strpos($value,$describe) === false ? 'true' : 'false';
|
|
|
- break;
|
|
|
- case "等于":
|
|
|
- $str = $value == $describe ? 'true' : 'false';
|
|
|
- break;
|
|
|
- case "小于":
|
|
|
- $str = $value < $describe ? 'true' : 'false';
|
|
|
- break;
|
|
|
- case "大于":
|
|
|
- $str = $value > $describe ? 'true' : 'false';
|
|
|
- break;
|
|
|
- case "小于等于":
|
|
|
- $str = $value <= $describe ? 'true' : 'false';
|
|
|
- break;
|
|
|
- case "大于等于":
|
|
|
- $str = $value >= $describe ? 'true' : 'false';
|
|
|
- break;
|
|
|
- default:
|
|
|
- $str = 'false';
|
|
|
- }
|
|
|
- continue;
|
|
|
- }
|
|
|
- if ($str == "&") {
|
|
|
- $str = '&&';
|
|
|
- continue;
|
|
|
- }
|
|
|
- if ($str == "|") {
|
|
|
- $str = '||';
|
|
|
- }
|
|
|
- }
|
|
|
- $is = implode("",$result[0]);
|
|
|
- return eval("return $is;");
|
|
|
+ if (!isset($features[$id]))return 'false'; //特征不存在返回 false
|
|
|
+ if (!($columnMapping[$features[$id]["type"]] ?? false))return 'false';
|
|
|
+ return $this->getMatchBool($features[$id],$matchObject,explode(".",$columnMapping[$features[$id]["type"]]));
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 多重子项匹配
|
|
|
+ * 获取匹配结果
|
|
|
*
|
|
|
- * @param array $packages
|
|
|
- * @param string $logic
|
|
|
- * @param string $describe
|
|
|
- * @param string $column
|
|
|
- * @return string //"true" || "false"
|
|
|
+ * @param array $feature
|
|
|
+ * @param array|\stdClass $matchObject
|
|
|
+ * @param array $column
|
|
|
+ *
|
|
|
+ * @return string
|
|
|
*/
|
|
|
- private function multiMatching($packages, $logic, $describe, $column):string
|
|
|
+ private function getMatchBool($feature, $matchObject, $column)
|
|
|
{
|
|
|
- if(!$column)return 'false';
|
|
|
-
|
|
|
- foreach ($packages as $package){
|
|
|
- $value = $package[$column] ?? '';
|
|
|
+ /*递归: 1.列数组为空 对象不存在列 返回false
|
|
|
+ 2.为数组时,递归数组内对象,任意一个符合返回true,全部不符合返回false
|
|
|
+ 3.为正常值时,进入核心匹配,必然返回一个值
|
|
|
+ 4.为对象时,向下递归,splice列数组
|
|
|
+ */
|
|
|
+ if (!$column)return 'false';
|
|
|
+ if (!isset($matchObject[$column[0]]))return 'false';
|
|
|
+ if (is_array($matchObject)){
|
|
|
+ foreach ($matchObject as $object){
|
|
|
+ if ($this->getMatchBool($feature,$object,$column) === 'true')return 'true';
|
|
|
+ }
|
|
|
+ return 'false';
|
|
|
+ }
|
|
|
+ $value = $matchObject[$column[0]];
|
|
|
+ if (count($column)==1 && (is_string($value) || is_numeric($value) || is_null($value))){
|
|
|
+ $logic = $feature["logic"];
|
|
|
+ $describe = $feature["describe"];
|
|
|
switch ($logic) {
|
|
|
case "包含":
|
|
|
- if (mb_strpos($value,$describe)!==false)return 'true';
|
|
|
+ if (mb_strpos($value,$describe) !== false)return 'true';
|
|
|
break;
|
|
|
case "不包含":
|
|
|
if (mb_strpos($value,$describe) === false)return 'true';
|
|
|
@@ -329,8 +319,10 @@ class FeatureService
|
|
|
if ($value >= $describe)return 'true';
|
|
|
break;
|
|
|
}
|
|
|
- }
|
|
|
- return "false";
|
|
|
+ return 'false';
|
|
|
+ };
|
|
|
+ array_splice($column,0,1);
|
|
|
+ $this->getMatchBool($feature, $value, $column);
|
|
|
}
|
|
|
|
|
|
}
|