获取匹配特定条件的数组的键仅适用于零键

时间:2019-03-03 17:36:53

标签: php arrays foreach

我有这个循环,应该返回与某些条件匹配的键号(其中几个内部键的md5与客户端报告的字符串匹配)。

foreach ( $response->posts as $key => $element ) {
    if ( $postData['sign'] == md5($api_secret.$postData['date'].$response->count.$element->text) ) {
        break;
    }
    elseif ( $postData['sign'] == md5($api_secret.$postData['date'].$postData['num'].$element->text) ) {
        $log_msg = date('H:i:s').' Comment "'.$postData['last_comment'].'" saved with less accuracy (another comment added before it was saved)';
        $this->wh_log($log_msg);
        break;
    }
    else {
        $log_msg = date('H:i:s').' Couldn\'t save the comment "'.$postData['last_comment'].'" sent from '.$ip.' because it failed the integrity check';
        $this->wh_log($log_msg);
        return $this->save_level2($access_token, $response, $referer);
    }
}
echo 'level 1 $key is '.$key.' || ';

问题在于,在进一步测试期间,结果发现,如果在零键($response->posts[0]中找不到满足条件,那么它将立即继续使用最后一个条件(在{{1中定义}}),并创建一个带有错误的日志文件,甚至没有尝试在其他键(例如1、2等)中查找会议条件。我的echo函数说else,但它应该在满足条件的键中回显条件。但是由于某种原因,它似乎并没有超出零键。

//我编辑了代码,以使其不包含人们不会认可的变量。

3 个答案:

答案 0 :(得分:0)

首先,为了正确起见,原始问题“为什么只考虑第一个键”的答案仍然是:

return将立即结束函数(如果在函数内部)或脚本/文件(否则)。并且无论是否处于循环中,它都会返回。因此,第一次执行else分支时,循环由于return而结束,在所有其他分支中,循环因break

而结束

但是,要解决潜在的问题:

要解决的问题是: 找到与条件1匹配的第一个键(如果不存在),找到与条件2匹配的第一个键,如果没有,则输出一些通用内容(错误输出)。

有很多方法可以解决此问题,主要的区别在于循环是运行一次还是运行两次。由于您已经确定了您的条件,因此我将它们分别称为$cond1$cond2

$cond1key = $cond2key = null; // <-- this stores what we'll find
foreach($response->posts as $key => $element) {
    if($cond1) {
         // if we find a key, for which $cond1 is true, we can abort
         $cond1key = $key;
         break;
    } elseif(!$cond2key && $cond2) {
         // if we find a key, for which $cond2 is true, there still
         // may be a key, for which $cond1 is true, so no break.
         // also notice the !$cond2key in the if statement, this 
         // prevents overwriting
         $cond2key = $key;
    }
 }
 // now we look at the results of our "search"
 if($cond1key) {
     // key found by condition 1
     echo 'level 1 $key is '.$cond1key.' || ';
 } elseif($cond2key) {
     // key found by condition 2
     $log_msg = date('H:i:s').' Comment "'.$postData['last_comment'].'" saved with less accuracy (another comment added before it was saved)';
     $this->wh_log($log_msg);
 } else {
     // no key found
     $log_msg = date('H:i:s').' Couldn\'t save the comment "'.$postData['last_comment'].'" sent from '.$ip.' because it failed the integrity check';
     $this->wh_log($log_msg);
     return $this->save_level2($access_token, $response, $referer);
 }

现在,我在那里只使用了一个循环,重复循环也是可能的(现在是非常简化的代码):

 foreach($response->posts as $key => $value) {
     if($cond1) {
          $cond1key = $key;
          break;
     }
 }
 if(!$cond1key) {
     foreach($response->posts as $key => $value) {
         if($cond2) { // no danger of overwriting, since we break ...
             $cond2key = $key;
             break; // since we're only looking for a cond2 key now.
         }
     }
 }
 // conditional code execution as before

现在,这段代码是我可以说的最简单的代码。还有一些更优雅的解决方案,这些解决方案在理解方面没有任何真正的好处,这绝对不是赢得任何竞赛的本分; o)

注意:$cond1key / $cond2key显然是不好的名字,如果您在语义上更适合这些变量,请使用它们。

希望这会有所帮助; o)

答案 1 :(得分:0)

您不是要遍历值($ elements)...它将始终在一次迭代后退出:

  • 如果条件为 true ->将打破循环= 无迭代
  • 如果条件二为 true ->将打破循环= 无迭代
  • 如果两者均为 false ->将返回=中断循环并退出函数= 无迭代

我不确定您要做什么-根据您的问题,当哈希值相等时,您希望迭代中断,否则继续迭代->重新考虑使用这些中断并返回,我想您想要使用其他类似CONTINUE的东西。

示例:

//Consider this example inputs based on your question:
$secret = "bla";
$date = "00:00:0000";
$num  = 1;
$postData = [
    "example sign1" => md5($secret.$date."postdatahere with date"),
    "example sign2" => md5($secret.$num."postdatahere with num"),
    "date"  => $date,
    "num"   => $num
];
$posts = [
    "key1" => ["text" => "postdatahere with date"],
    "key2" => ["text" => "postdatahere with num"],
    "key3" => ["text" => "will exit the loop"]
];

//Run -> check_postdata is the function containing the logic:
echo check_postdata($posts, $postData, $secret, "example sign1")."\n";
echo check_postdata($posts, $postData, $secret, "example sign2")."\n";

使用您的方法简化示例1:

//Using this logic with the BREAKs:
function check_postdata($posts, $postData, $secret, $example) {
    foreach ( $posts as $key => $element ) {

        //Same as the md5 part:
        $correct_value_date = md5($secret.$postData["date"].$element["text"]);
        $correct_value_num = md5($secret.$postData["num"].$element["text"]); 

        if ( $postData[$example] === $correct_value_date ) {
            echo "  -  ".$key." -> break in IF block!\n";
            break;
        }
        elseif ( $postData[$example] === $correct_value_num ) {
            echo "  -  ".$key." -> break in ELSEIF block!\n";
            break;
        } else {
            echo "  -  ".$key." -> continue in ELSE block!\n";
            return 0;
        }

    }
    return 1;
}
/*  The Result is:
 *
 *  -  key1 -> break in IF block!
 *  1
 *  -  key1 -> continue in ELSE block!
 *  0
 */

使用 CONTINUE的简化示例2:

//Using this logic with the CONTINUE:
function check_postdata($posts, $postData, $secret, $example) {
    foreach ( $posts as $key => $element ) {

        //Same as the md5 part:
        $correct_value_date = md5($secret.$postData["date"].$element["text"]);
        $correct_value_num = md5($secret.$postData["num"].$element["text"]); 

        if ( $postData[$example] === $correct_value_date ) {
            echo "  -  ".$key." -> break in IF block!\n";
            break;
        }
        elseif ( $postData[$example] === $correct_value_num ) {
            echo "  -  ".$key." -> break in ELSEIF block!\n";
            break;
        } else {
            echo "  -  ".$key." -> return in ELSE block!\n";
            continue;
        }

    }
    return "Returned key is: ".$key;
}
/*  The Result is:
 *
 *    -  key1 -> break in IF block!
 *  Returned key is: key1
 *    -  key1 -> continue in ELSE block!
 *    -  key2 -> break in ELSEIF block!
 *  Returned key is: key2
 */

如您所见,使用逻辑是没有意义的,因为它总是会迭代一次并停止。 使用CONTINUE方法将迭代直到条件之一为真。

希望我有帮助。

答案 2 :(得分:0)

最终解决了该问题。我必须创建一个仅在找到匹配项后才设置的变量。另外,每次找不到匹配项时,我都必须继续循环。我认为无论如何都将继续下去,直到满足条件为止,但是我错了。这是可行的解决方案:

foreach ( $response->posts as $key => $element ) {
    if ( $postData['sign'] == md5($api_secret.$postData['date'].$response->count.$element->text) ) {
        $key_obtained = $key;
        break;
    }
    else continue;
    if ( $postData['sign'] == md5($api_secret.$postData['date'].$postData['num'].$element->text) ) {
        $key_obtained = $key;
        $log_msg = date('H:i:s').' Comment "'.$postData['last_comment'].'" saved with less accuracy (another comment added before it was saved)';
        $this->wh_log($log_msg);
        break;
    }
    else continue;
    if ( !isset ($key_obtained) ) {
        $log_msg = date('H:i:s').' Couldn\'t save the comment "'.$postData['last_comment'].'" sent from '.$ip.' because it failed the integrity check';
        $this->wh_log($log_msg);
        return $this->save_level2($access_token, $response, $referer);
    }
}
echo 'level 1 $key is '.$key.' || ';