我有这个循环,应该返回与某些条件匹配的键号(其中几个内部键的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
,但它应该在满足条件的键中回显条件。但是由于某种原因,它似乎并没有超出零键。
//我编辑了代码,以使其不包含人们不会认可的变量。
答案 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)...它将始终在一次迭代后退出:
我不确定您要做什么-根据您的问题,当哈希值相等时,您希望迭代中断,否则继续迭代->重新考虑使用这些中断并返回,我想您想要使用其他类似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.' || ';