PHP try / catch и фатальная ошибка

Я использую следующий скрипт для использования базы данных с помощью PHP:

try{ $db = new PDO('mysql:host='.$host.';port='.$port.';dbname='.$db, $user, $pass, $options); } catch(Exception $e){ $GLOBALS['errors'][] = $e; } 

Теперь я хочу использовать этот дескриптор базы данных для выполнения запроса с помощью этого кода:

 try{ $query = $db->prepare("INSERT INTO users (...) VALUES (...);"); $query->execute(array( '...' => $..., '...' => $... )); } catch(Exception $e){ $GLOBALS['errors'][] = $e; } 

Вот проблема:

  • Когда соединение с БД в порядке, все работает,
  • Когда соединение терпит неудачу, но я не использую БД, у меня есть массив $GLOBALS['errors'][] и скрипт все еще работает после этого,
  • Когда соединение с БД завершилось неудачно, я получаю следующую фатальную ошибку:

Примечание. Неопределенная переменная: db в C: \ xampp \ htdocs […] \ test.php в строке 32

Неустранимая ошибка: вызовите функцию-член prepare () для не-объекта в C: \ xampp \ htdocs […] \ test.php в строке 32

Примечание. Строка 32 – это команда $query = $db->prepare(...) .

То есть, сценарий падает, а try / catch кажется бесполезным. Вы знаете, почему эта вторая попытка / уловка не работает и как ее решить?

Спасибо за помощь!

EDIT: Есть действительно хорошие ответы. Я подтвердил то, что не совсем то, что я хотел сделать, но это, вероятно, лучший подход.

try / catch блоки работают только для сброшенных исключений ( throw Exception или подкласс Exception ). Вы не можете поймать фатальные ошибки, используя try / catch .

Если ваше соединение с БД не может быть установлено, я считаю его фатальным, так как вам, вероятно, нужна ваша БД, чтобы сделать что-либо значимое на странице.

PDO выдает исключение, если соединение не может быть установлено. Ваша конкретная проблема заключается в том, что $db не определяется при попытке вызвать метод с ним, чтобы вы получили нулевой указатель (сорт), который является фатальным. Вместо того, чтобы перепрыгивать, if ($db == null) обручи, как предлагают другие, вы должны просто исправить свой код, чтобы убедиться, что $db либо всегда определяется, когда вам это нужно, либо имеет менее хрупкий способ убедиться, что соединение с БД доступен в коде, который его использует.

Если вы действительно хотите «уловить» фатальные ошибки, используйте set_error_handler , но это все еще останавливает выполнение сценария при фатальных ошибках.

Если соединение с базой данных завершается неудачно, $db с первой try .. catch блокирует try .. catch . Вот почему позже вы не можете использовать член не-объекта, в вашем случае $db->prepare(...) . Перед использованием этого добавить

 if ($db) { // other try catch statement } 

Это гарантирует, что у вас есть экземпляр db для работы с ним.

Почему вы используете try ... catch заявления для объявления этого. Замените это:

 try{ $db = new PDO('mysql:host='.$host.';port='.$port.';dbname='.$db, $user, $pass, $options); } 

С:

 $db = new PDO('mysql:host='.$host.';port='.$port.';dbname='.$db, $user, $pass, $options) or die("Cannot Create PDO!"); 

Или на вашем пути:

 $db = new PDO('mysql:host='.$host.';port='.$port.';dbname='.$db, $user, $pass, $options) or ($GLOBALS['errors'][] = "Cannot Create PDO!"); 

Попробуйте добавить следующую инструкцию if:

 if ($db) { $query = $db->prepare("INSERT INTO users (...) VALUES (...);"); $query->execute(....); } else die('Connection lost'); 
 try{ if(!is_null($db)) { $query = $db->prepare("INSERT INTO users (...) VALUES (...);"); $query->execute(array( '...' => $..., '...' => $... )); } } catch(Exception $e){ $GLOBALS['errors'][] = $e; }