How DBAL throws errors
I checked and it looks, that DBAL for PDO related drivers, by default sets PDO::ATTR_ERRMODE
to PDO::ERRMODE_EXCEPTION
(here and here), so we have detailed stack trace like in PDO.
In fact DBAL exception, is even little more detailed than PDO - DBAL adds some info to the description of the error (for example here).
Options to change level of errors
It seems, that DBAL lacks feature to change level of how it throw errors.
There is no way to change PDO::ATTR_ERRMODE
to PDO::ERRMODE_SILENT
or PDO::ERRMODE_WARNING
.
In theory, it should be available by driverOptions option, something like this:
$params = array(
'dbname' => $options['dbname'],
'user' => $options['user'],
'password' => $options['pass'],
'host' => $options['host'],
'port' => $options['port'],
'driver' => 'pdo_mysql',
'charset' => $options['charset'],
'driverOptions' => array(
3 => 0 //here "3" is value of constant ATTR_ERRMODE, and "0" value of constant ERRMODE_SILENT
)
);
It would work, but soon after connection declaration, DBAL overwrites PDO::ATTR_ERRMODE
(here).
Within PDO there is also setAttribute
method, with it we would be able to set PDO::ATTR_ERRMODE
, but unfortunately DBAL do not implement setAttribute
method.
How to control errors in DBAL
In DBAL we already have the best level of errors, we can catch everything and to better control we can use set_error_handler
:
<?php
/**
* Error handler
*
* @param int $err_code the numeric error code
* @param str $err_str description of the error
* @param str $err_file the name of the file that contains the error
* @param int $err_line the line number of the error
* @param str $err_context details of the error
*/
function errorHandler($err_code, $err_str, $err_file, $err_line, $err_context) {
global $_SESSION;
$_SESSION['errorCounter']++;
$error_types = array (
E_WARNING => 'WARNING',
E_NOTICE => 'NOTICE',
E_USER_ERROR => 'USER ERROR',
E_USER_WARNING => 'USER WARNING',
E_USER_NOTICE => 'USER NOTICE',
E_STRICT => 'STRICT',
E_DEPRECATED => 'DEPRECATED',
E_USER_DEPRECATED => 'USER DEPRECATED'
);
$error_type = isset($error_types[$err_code]) ? $error_types[$err_code] : 'UNKNOWN ERROR TYPE['.$err_code.']';
$err = "\n>--------------------------------------------------------------------";
$err .= "\n".'EXCEPTION #'.$_SESSION['errorCounter'].':';
$err .= "\n\n---- PHP ".$error_type.": ----";
$err .= "\n".$err_str;
//$err .= print_r($err_context, 1);
if (isset($err_context['e'])){
$err .= "\n\n---- STACKTRACE: ----";
$dir_root = $_SERVER["DOCUMENT_ROOT"];
$err .= "\nroot: " . $dir_root;
foreach ($err_context['e']->getTrace() as $a => $b) {
$err .= "\n" . strval($a) . '# ';
foreach ($b as $c => $d) {
switch($c){
case 'file':
$err .= str_replace($dir_root,'(root)',str_replace('\\','/',$d));
break;
case 'line':
$err .= '(' . $d . "); ";
break;
case 'function':
$err .= $c . ' ' . $d . "; ";
break;
case 'class':
$err .= $c . ' ' . $d . "; ";
break;
case 'type':
$err .= $c . ': ' . $d . "; ";
break;
case 'args':
foreach ($d as $e => $f){
$e = is_object($e) ? 'object' : is_array($e) ? 'array' : trim(preg_replace('/\s+/', ' ', $e));//do not return objects, arrays and change new lines to space
$f = is_object($f) ? 'object' : is_array($f) ? 'array' : trim(preg_replace('/\s+/', ' ', $f));//do not return objects, arrays and change new lines to space
$err .= 'args-' . $e . ': ' . $f . '; ';
}
break;
}
}
}
}
else {
$err .= "\n\n---- LOCATION: ----";
$err .= "\n".$err_file.'(' . $err_line . ')';
}
$err .= "\n\n---- CONNECTION: ----";
$err .= "\n".'host: '.$_SERVER['SERVER_NAME'];
$err .= "\n".'client: '.$_SERVER['REMOTE_ADDR'];
$err .= "\n".'timestamp: '.date("d-m-Y h:i:s A");
$err .= "\n<--------------------------------------------------------------------\n";
if (ini_get('log_errors')) {
error_log($err, 0);
if($err_code == E_USER_ERROR) {
if (!$_SESSION['options']['debug']) {
//send email with error
}
}
}
if ($_SESSION['options']['debug'])
print("\n<pre>".$err."</pre>\n");
return true;
}
set_error_handler("errorHandler");