[英]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.