简体   繁体   中英

Stop foreach loop when curl return 200

I try to communicate with my Proxmox cluster which contain 3 servers, from API. Goal is to connect to at least 1 of these servers in case of failure then execute other code (not visible here).

With the below code, I connect to these servers 1 by 1 using "foreach" and I want this loop stop when one server return "200" from Curl (so I can continue with this online server). For the test, I stopped the first server and let online the others 2 but the "foreach" loop keep connect the third server.

Any idea ? Thank you and sorry for my english.

<?php

$datas = array(
    array(
        "apiurl" => "192.168.1.34:8006",
        "node" => "pve1",
        "user" => "root",
        "userpass" => "pass",
    ),
    array(
        "apiurl" => "192.168.1.35:8006",
        "node" => "pve2",
        "user" => "root",
        "userpass" => "pass",
    ),
    array(
        "apiurl" => "192.168.1.36:8006",
        "node" => "pve3",
        "user" => "root",
        "userpass" => "pass",
    )
);

do {
    foreach ($datas as $data) {
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, 'https://'.$data['apiurl'].'/api2/json/access/ticket');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, 'username='.$data['user'].'@pam&password='.$data['userpass']);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_TIMEOUT, 2);

        $headers = array();
        $headers[] = 'Content-Type: application/x-www-form-urlencoded';

        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        $result = curl_exec($ch);

        if (curl_errno($ch)) {
            echo 'Server ' .$data['node']. ' is not reachable (error : ' .curl_error($ch). ')<br>';
        }
        else {
            $myArray = json_decode($result, true);
            $cookie = $myArray['data']['ticket'];
            $info = curl_getinfo($ch);
            echo "Server " .$data['node']. " is reachable (code is : " .$info['http_code']. ")<br>";
        }
    curl_close($ch);
    }
} while ($info['http_code'] !== 200);
?>

You can break out of an outer loop by giving an argument to break . break 2 means to break out of the second containing loop.

while (true) {
    foreach ($datas as $data) {
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, 'https://'.$data['apiurl'].'/api2/json/access/ticket');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, 'username='.$data['user'].'@pam&password='.$data['userpass']);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_TIMEOUT, 2);

        $headers = array();
        $headers[] = 'Content-Type: application/x-www-form-urlencoded';

        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        $result = curl_exec($ch);

        if (curl_errno($ch)) {
            echo 'Server ' .$data['node']. ' is not reachable (error : ' .curl_error($ch). ')<br>';
        }
        else {
            $myArray = json_decode($result, true);
            $cookie = $myArray['data']['ticket'];
            $info = curl_getinfo($ch);
            echo "Server " .$data['node']. " is reachable (code is : " .$info['http_code']. ")<br>";
            if ($info['http_code'] == 200) {
                break 2;
            }
        }
        curl_close($ch);
    }
}

What you have here is an infinite loop, because as you stated you already know the last 2 servers in the array won't respond successfully, yet your foreach loop will try all 3 regardless of success or failure. So by the time you get to the 3rd iteration of the foreach loop you get a failed response and then you reach the end of the while loop which determines the condition is still true and continues. To prevent this simply break from the foreach loop once success is determined. Because only then will the condition of the while loop become false . You can also break out of both loops if you'd like (using break 2 ). Either one is correct. The only difference is if you wanted any remaining logic inside the outter ( while ) loop to happen regardless of success or failure.

foreach ($datas as $data) {
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, 'https://'.$data['apiurl'].'/api2/json/access/ticket');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, 'username='.$data['user'].'@pam&password='.$data['userpass']);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_TIMEOUT, 2);

        $headers = array();
        $headers[] = 'Content-Type: application/x-www-form-urlencoded';

        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        $result = curl_exec($ch);

        if (curl_errno($ch)) {
            echo 'Server ' .$data['node']. ' is not reachable (error : ' .curl_error($ch). ')<br>';
        }
        else {
            $myArray = json_decode($result, true);
            $cookie = $myArray['data']['ticket'];
            $info = curl_getinfo($ch);
            echo "Server " .$data['node']. " is reachable (code is : " .$info['http_code']. ")<br>";
            if (!empty($info['http_code']) && $info['http_code'] == 200) {
                break; // break out of either or both loops since we got a valid response
            }
        }
    curl_close($ch);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM