[英]PHP array_filter on OR operator
我正在使用array_filter
将过滤器数组应用于数据数组。 函数调用看起来像$data = array_filter($tmpData, function($row) use $filterData { ... });
.
如果我在过滤每个过滤器的逻辑为 AND 的地方,这很好用。 但是,如果我想使用 OR 在两个值之间进行过滤,那么我对如何处理这个问题感到有些不安,因为每个过滤器也可以有一组嵌套的更多过滤器,这些过滤器会递归调用过滤函数。 过滤器的格式如下:
$filter = array(
'logic' => 'AND',
'filters' => array(
array('field' => $myFieldName1, 'operator' => $filterOperator1, 'value' => $myValue1),
array(
'logic' => 'OR',
'filters' => array(
array('field' => $myFieldName2, 'operator' => $filterOperator2, 'value' => $myValue2),
array('field' => $myFieldName3, 'operator' => $filterOperator3, 'value' => $myValue3)
)
)
)
);
你可以在这里看到我的函数的一个稍微精简的版本。 除了“等于”之外,它只实现了一个过滤器运算符。 https://www.tehplayground.com/FiPHxwDNJWdKq4hM
感谢您对制作此作品的 OR 部分的任何帮助。
我认为递归函数会让你到达那里。 首先,我将模拟一些类似于你的数据,但可能更简单一点:
$obj = new stdClass();
$obj->a = 5;
$obj->b = 2;
$obj->c = 9;
$filter = array(
'logic' => 'AND',
'filters' => array(
array('field' => 'a', 'operator' => '===', 'value' => 5),
array(
'logic' => 'OR',
'filters' => array(
array('field' => 'b', 'operator' => '===', 'value' => 6),
array('field' => 'c', 'operator' => '<', 'value' => 10),
),
),
),
);
然后,我们正在编写一个递归函数。 我正在使用 PHP 8 的match
,这使得这非常简洁,但您可能需要根据您的 PHP 版本进行更改。 有关更多详细信息,请参阅代码注释。 这不是最有效的,但它应该可以完成工作。
function process(string $logic, array $filters, object $obj): bool
{
// For an AND, all things must be true, so if we're given 5 things, all 5 must be true.
// For an OR, only one needs to be true.
$targetCount = 'AND' === $logic ? count($filters) : 1;
// How many items were true
$currentCount = 0;
foreach ($filters as $filter) {
// The sub-array is a grouping, grab parts, process, and if true, increment our local counter
if (array_key_exists('logic', $filter)) {
if (process($filter['logic'], $filter['filters'], $obj)) {
$currentCount++;
}
// For a sub-array, don't process anything else
continue;
}
// Grab array items as variables just for ease of use
$field = $filter['field'];
$operator = $filter['operator'];
$value = $filter['value'];
// Match on the operator. For lower versions of PHP a switch(true) or just an if could be used, too.
$result = match ($operator) {
'===' => $obj->$field === $value,
'==' => $obj->$field == $value,
'>=' => $obj->$field >= $value,
'>' => $obj->$field > $value,
'<=' => $obj->$field <= $value,
'<' => $obj->$field < $value,
};
// If success, increment our counter
if ($result) {
$currentCount++;
// If we've reach our target, return success
// This could also just be "if process = OR"
if ($currentCount === $targetCount) {
return true;
}
}
}
// See if we met the final condition outside of the loop
return $currentCount === $targetCount;
}
最后,一个调用它的例子。 对于递归函数,您通常必须确定是否要让整个函数尝试并确定它是否是第一次迭代并进行设置,或者是否要传递设置以便每次迭代都运行相同,并且我我做了后者。
echo process($filter['logic'], $filter['filters'], $obj) ? 'yes' : 'no';
在线示例在这里: https : //3v4l.org/Hu0CY#v8.0.8
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.