Problem, który miałem z rozwiązaniem do przechwytywania wyjątków PDO do celów debugowania polega na tym, że wychwycił on tylko wyłączenia PDO (duh), ale nie przechwycił błędów składniowych, które zostały zarejestrowane jako błędy php (nie jestem pewien, dlaczego tak jest, ale „ dlaczego ”nie ma znaczenia dla rozwiązania). Wszystkie moje wywołania PDO pochodzą z jednej klasy modelu tabeli, którą rozszerzyłem dla wszystkich moich interakcji ze wszystkimi tabelami ... to skomplikowane rzeczy, gdy próbowałem debugować kod, ponieważ błąd zarejestrowałby wiersz kodu php, w którym znajdowało się moje wywołanie wykonania zadzwonił, ale nie powiedział mi, skąd właściwie dzwoni. Użyłem poniższego kodu, aby rozwiązać ten problem:
/**
* Executes a line of sql with PDO.
*
* @param string $sql
* @param array $params
*/
class TableModel{
var $_db; //PDO connection
var $_query; //PDO query
function execute($sql, $params) {
//we're saving this as a global, so it's available to the error handler
global $_tm;
//setting these so they're available to the error handler as well
$this->_sql = $sql;
$this->_paramArray = $params;
$this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->_query = $this->_db->prepare($sql);
try {
//set a custom error handler for pdo to catch any php errors
set_error_handler('pdoErrorHandler');
//save the table model object to make it available to the pdoErrorHandler
$_tm = $this;
$this->_query->execute($params);
//now we restore the normal error handler
restore_error_handler();
} catch (Exception $ex) {
pdoErrorHandler();
return false;
}
}
}
Tak więc powyższy kod wyłapuje ZARÓWNO wyjątki PDO ORAZ błędy składniowe php i traktuje je w ten sam sposób. Mój program obsługi błędów wygląda mniej więcej tak:
function pdoErrorHandler() {
//get all the stuff that we set in the table model
global $_tm;
$sql = $_tm->_sql;
$params = $_tm->_params;
$query = $tm->_query;
$message = 'PDO error: ' . $sql . ' (' . implode(', ', $params) . ") \n";
//get trace info, so we can know where the sql call originated from
ob_start();
debug_backtrace(); //I have a custom method here that parses debug backtrace, but this will work as well
$trace = ob_get_clean();
//log the error in a civilized manner
error_log($message);
if(admin(){
//print error to screen based on your environment, logged in credentials, etc.
print_r($message);
}
}
Jeśli ktoś ma lepszy pomysł, jak uzyskać odpowiednie informacje do mojego modułu obsługi błędów niż ustawienie modelu tabeli jako zmiennej globalnej, byłbym szczęśliwy, słysząc to i edytując swój kod.
/var/log/mysql/*
. Parametry związane z PDO nie mogą powodować błędów składniowych, więc wszystko, czego potrzebujesz, to przygotowane zapytanie SQL.