У меня где-то использовался `язык фильтров` - строка с условиями, которую удобно вписывать в область фильтра в столбик таблицы с данными. Постим на сервер - получаем фильтрованное.
Сама строка условий выглядит примерно так
count=2,<2;count=3,<300,>44
условия соединяются запятой, по AND, точкой с запятой - по OR, у OR более низкий приоритет. Операция сравнения соединяет 2 операнда, если один из операндов пустой - берется "сравниваемое значение", если число - то число, иначе ищем во внешних "данных".
Если записать строку на php - будет что-то вроде
$current=45; // значение, которое сравниваем
$data=['count'=>3]; // внешние данные
if( ($data['count']==2 && $current<2) || ($data['count']==3 &&$current>44 && $current<300)){
// ...
}
Удобно в языке то, что парсер его компактен и легко допиливается напильником по месту.
function evaluate($current,$cond,$data=[]){
$res=false;
foreach(explode(';',$cond) as $or){ //or
foreach(explode(',',$or) as $and) { //and
if(preg_match('/^(.*?)(<=|>=|<|>|=)(.*?)$/',$and,$m)){
$a=trim($m[1]);$b=trim($m[3]);
if(empty($a)) $a=$current;
else if(is_numeric($a)) $a=0+$a;
else if(isset($data[$a])) $a=$data[$a];
else {
$res=false; break;
}
if(empty($b)) $b=$current;
else if(is_numeric($b)) $b=0+$b;
else if(isset($data[$b])) $b=$data[$b];
else {
$res=false; break;
}
if($m[2]=='<=') $res=$a<=$b;
else if($m[2]=='>=') $res=$a>=$b;
else if($m[2]=='>') $res=$a>$b;
else if($m[2]=='<') $res=$a<$b;
else if($m[2]=='=') $res=$a==$b;
} else {
$res=false;
//throw new \Exception('Некорректное условие в строке '.$and)
}
if(!$res) break; // выход по AND
}
if($res) break; // выход по OR
}
return $res;
}
$data=['count'=>3];
var_dump(true===evaluate(45,'count=2,<2;count=3,<300,>44', $data));
var_dump(true===evaluate(1,'<2'));
var_dump(true===evaluate(1,'>3;<2,>1;<2'));