Возобновить PHP для выполнения скрипта после исключения


У меня есть php-скрипт, позволяющий сказать, что во время выполнения скрипты выдают исключение. Я хочу, чтобы мой PHP возобновился с того места, на котором он остановился (где он создал исключение).

Должен ли я поместить тот же код выполнения в часть кода "поймать"?

Например, допустим, что при подключении к MySQL происходит сбой из-за истечения времени ожидания соединения

   function someCode(){
        $pdostmt = $this->prepare($this->sql);
        if($pdostmt->execute($this->bind) !== false) {
            if(preg_match("/^(" . implode("|", array("select", "describe", "pragma")) . ") /i", $this->sql))
                return $pdostmt->fetchAll($this->fetchOption);
            elseif(preg_match("/^(" . implode("|", array("delete", "insert", "update")) . ") /i", $this->sql))
                return $pdostmt->rowCount();
   }
   try {
        someCode();
        }   
    } catch (PDOException $e) {  
        //re-execute same code as within the try clause?
        someCode();
    }
Author: MCHam, 2012-12-19

4 answers

Прежде всего, следует четко указать, что исключение является фатальным только в том случае, если оно не поймано . Обнаружение исключения не останавливает выполнение скрипта. Он просто останавливает кадр стека в блоке try и передает управление блоку catch. Оттуда ваш скрипт продолжит выполняться в обычном режиме.

Поймав исключение здесь, мы все равно возобновим обычное выполнение скрипта после того, как исключение будет поймано...

try {
  echo "Try...\n";
  throw new Exception("This is an exception");
} catch(Exception $e) {
  echo "Exception caught with message: " . $e->getMessage() . "\n";
}

echo "Script is still running...";

Что вам может понадобиться, так это обработчик исключений . Использовать обработчик исключений, чтобы вам не приходилось обрабатывать каждое исключение в try/catch блоки вы можете сделать следующее...

function myExceptionHandler($e) {
  echo "Uncaught exception with message: " , $e->getMessage(), "\n";
}

set_exception_handler('myExceptionHandler'); // Registers the exception handler

throw new Exception("This is Exception 1");
throw new Exception("This is Exception 2");
throw new Exception("This is Exception 3");
echo "The script is still running...";

Редактировать: После уточнения вашего вопроса я думаю, что я должен указать, что вы хотите не обработчик исключений, но на самом деле вы вообще не хотите использовать исключения. То, что вы пытаетесь сделать, вообще не требует создания исключений. Не переводите PDO в режим исключения, если вы намерены просто обработать ошибка вроде этой. Исключение должно использоваться только для обработки исключительных ошибок. Весь смысл исключения в том, чтобы убедиться, что вы сдержите свое обещание. Например, если ваша функция обещает, что она всегда будет возвращать объект PDOStatement, и есть случай, когда она не может этого сделать, тогда имеет смысл создать исключение. Это позволяет звонящему узнать, что мы достигли точки, когда мы не можем сдержать свое обещание.

То, что вы хотите, - это основная ошибка обращение...

function someCode(){
        $pdostmt = $this->prepare($this->sql);
        if($pdostmt->execute($this->bind) !== false) {
            if(preg_match("/^(" . implode("|", array("select", "describe", "pragma")) . ") /i", $this->sql))
                return $pdostmt->fetchAll($this->fetchOption);
            elseif(preg_match("/^(" . implode("|", array("delete", "insert", "update")) . ") /i", $this->sql))
                return $pdostmt->rowCount();
        } else {
           return false;
        }
}

while (someCode() === false) {
  /* Call someCode() until you get what you want */
}
 25
Author: Sherif, 2012-12-19 15:39:49

Используйте функцию php 4/5 register_shutdown_function.

Документ здесь: http://php.net/manual/en/function.register-shutdown-function.php

 3
Author: gf4gs56dg4sd56s, 2013-08-21 15:55:56

Я предполагаю, что вы не можете обработать исключение в создаваемой функции. Если вы хотите возобновить работу там, где было вызвано ваше исключение, вам нужно обработать исключение там. Все остальное - плохое кодирование, приводящее к путанице для вас или кого-либо еще, работающего над проектом. Мы позволяем исключениям подниматься по дереву, потому что мы не можем обрабатывать их в самой функции из-за проблем с областью действия.

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

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

Чтобы ответить на ваш вопрос просто и прямо. Нет, это плохая идея - вызывать функцию try(ed) в блоке catch, и простая причина в том, что у вас больше нет блока try, чтобы перехватить там исключение. Исключения обеспечивают более значимую обработку ошибок, чем просто передача значений true и false в качестве возврата. Однако, это это означает, что вы должны пройти полный круг в обращении с ними.

Теперь рассмотрим альтернативный пример... Допустим, у нас есть несколько серверов, к которым мы можем подключиться, и вы хотели запустить, подумав, что список, который вы бы поместили в цикл try/catch, и catch проверит это исключение и выполнит любую очистку перед выполнением следующего цикла. Если произойдет какое-либо другое исключение, мы (повторно) создадим исключение. Правильный способ достичь того, что вы ищете, был бы таким.

function someCode() {
    $pdostmt = $this->prepare($this->sql);

    while($status == false) {
        try {
            $status = $pdostmt->execute($this->bind)

        } catch (PDOException $e) {
            if($e->getMessage("What ever the error message is") {
                //Fix it here
            } else {
                throw $e;
            }
        }
    }
    //Do other stuff
    return $data; //or true/false
}
 3
Author: bgrohs, 2014-07-20 06:05:47

Возможно, вы сможете использовать последнюю часть try catch, если вы не получите исключение при выполнении.

try {
  // some crashing code
} catch (Exception $e) {
  //some catch code
} finally {
  //code that will run anyways.
}
 0
Author: jaudette, 2012-12-19 15:23:37