Остановка foreach l oop при возврате керла - PullRequest
0 голосов
/ 20 февраля 2020

Я пытаюсь связаться с моим кластером Proxmox, который содержит 3 сервера, из API. Цель состоит в том, чтобы подключиться по крайней мере к одному из этих серверов в случае сбоя, а затем выполнить другой код (здесь не отображается).

С помощью приведенного ниже кода я подключаюсь к этим серверам 1 на 1, используя «foreach», и я хочу, чтобы l oop остановился, когда один сервер вернул "200" из Curl (так что я могу продолжить работу с этим онлайн-сервером). Для теста я остановил первый сервер и подключил остальные 2, но «foreach» l oop продолжает подключать третий сервер.

Есть идеи? Спасибо и извините за мой английский sh.

<?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);
?>

Ответы [ 2 ]

0 голосов
/ 20 февраля 2020

Здесь у вас есть бесконечное число l oop, потому что, как вы заявили, вы уже знаете, что последние 2 сервера в массиве не будут отвечать успешно, но ваш foreach l oop попробует все 3 независимо от того, успех или неудача. Таким образом, когда вы дойдете до 3-й итерации foreach l oop, вы получите неудачный ответ, и затем вы достигнете конца while l oop, который определяет условие до сих пор true и продолжается. Чтобы предотвратить это, просто оторвитесь от foreach l oop, как только успех определен. Поскольку только , тогда станет условием while l oop и станет false. Вы также можете разорвать оба цикла, если хотите (используя break 2). Либо один правильный. Единственное отличие состоит в том, что если вы хотите, чтобы оставшиеся логики c внутри ауттера (while) l oop происходили независимо от успеха или неудачи.

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);
}
0 голосов
/ 20 февраля 2020

Вы можете выйти из внешнего l oop, указав аргумент break. break 2 означает вырваться из второго, содержащего l oop.

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);
    }
}
...