Продолжить текущую итерацию в блоке try-catch |PHP - PullRequest
0 голосов
/ 03 ноября 2019

В моем скрипте иногда возникают проблемы с сервером, соединением, конфигурацией или API, поэтому я реализовал блок try-catch, чтобы правильно перехватывать исключения и пропускать их.

... но моя проблема не решенас этим решением, поскольку элементы (которые бросили проблему) не являются самой проблемой. Так что, в основном, мой вопрос есть ли какой-нибудь способ перехватить ошибку и продолжить там, где вы оставили: не пропуская ошибку и переходя к следующему элементу, а повторяя текущую итерацию в цикле foreach.

Очевидно, продолжить и break не работают!

foreach($xx as $x) {
    try {
        //main code
    } catch (Exception $e) {
        echo 'Caught exception: ', $e->getMessage(), "\n";
        sleep(10);
    }
}

... и когда часть перехвата ловит ошибку, коддолжен повторить цикл try с текущим значением $ x (в котором он первоначально перехватил ошибку / сгенерировал ошибку), а затем продолжить со списком элементов.

Ответы [ 3 ]

0 голосов
/ 03 ноября 2019

Поместите блок try в свой собственный цикл while (true), который вы можете break в случае успеха:

while (true) {
    try {
        ...
        break;
    } catch (...) {
        ...
    }
}

Это повторяет одно и то же действие, пока не будет выброшено исключение. Чтобы избежать бесконечных циклов действий, которые просто никогда не будут успешными, вы можете добавить счетчик, например:

$tries = 0;
while ($tries < 10) {
    $tries++;
    try { ... }
}
0 голосов
/ 03 ноября 2019

Как только исключение выдается и перехватывается, пути назад к блоку кода, в котором было сгенерировано исключение, больше нет. Настолько неудачно, что нет технической возможности, что у вас есть только один блок try catch, в котором вы перехватываете все исключения и затем решаете, являются ли они важными (и прекращают ли выполнение сценария), или исключение не было реальной проблемой, и вы хотите, чтобы ваш сценарий вел себя какесли не было никаких исключений.

Единственное решение, которое я могу вам дать:

foreach($xx as $x) {
    try {
        //main code

        try {
            //first code that can cause an exception
            //you just want to continue after
        } catch (Exception $e) {
            echo "Nothing wrong, just an exception " . $e->getMessage(), "\n";
        }

        try {
            //second code that can cause an exception
            //a serious problem, you don't want to continue
        } catch (Exception $e) {
            echo "This is a real problem " . $e->getMessage(), "\n";
            throw $e; //re-trowing exception
        }

        //third code that can cause an exception

    } catch (Exception $e) {
        //will catch exception from code 2 and 3 but not 1.

        echo 'Caught exception: ', $e->getMessage(), "\n";
        sleep(10);
    }
}

Кстати. То, что вы просите, должно быть сделано не с использованием исключений, а в случае ошибок. Если об ошибке сообщается, и она может быть исправлена, вы можете написать глобальный обработчик для ошибок, и внутри этого дескриптора ошибки решить, является ли ошибка проблемой, вы хотите закрыть свой сценарий или просто зарегистрировать его и вернуться к выполнению сценария, как если быТам нет ошибки вообще. Но речь идет об ошибках, а не об исключениях.

0 голосов
/ 03 ноября 2019

Вы можете запустить цикл вместо цикла foreach и управлять счетчиком приращений внутри блока catch, уменьшив его, чтобы получить текущий $ x (для которого он первоначально перехватил ошибку / сгенерировал ошибку), и повторите попытку с тем жеэлемент. Это может вызвать бесконечный цикл, поэтому сохраняйте любой порог повторной попытки.

...