Muy buenas soluciones! Me encantaron, he probado con los códigos que me disteis y me sirvio para encontrar en el manual de php un comentario de set_error_handler() donde había un ejemplo muy completo para los errores de SQL.
He probado con y sin @ para silenciar el error y no se observaban cambios.
La primera solución no me ha funcionado, porque se muestra el contenido del
or die(mysql_error()); y no se captura la excepción.
Tal vez php no lo interprete como excepción al ser un warning.
La segunda solución, SI me ha funcionado, pero tengo algunas pegas.
Si pones el set_error_handler() como esta, todos otros posibles errores de PHP (como warnings o notice) se manejarian por ahi. Para evitar eso le añado otro parametro con los errores personalizados del usuario a traves de la constante E_USER_ERROR (equivalente a 256).
Con eso el manejador solo se accionara para errores personalizados que accionemos con un trigger y si queremos asegurarnos aun más podemos restaurar al manejador de php tras acabar la consulta.
Por otro lado, lanzo un error con un manejador en vez de llamar a die() y asi me permite dar más juego al mensaje y a otros posibles errores de usuario.
Os doy las gracias a los dos, porque me pusisteís en "pista" para descubrir por donde tenia que atacar este problema.
Creo que para mi esta bien resuelto, pongo el código por si a alguien más le surge la duda de como utilizarlo (los comentarios y nombres están en ingles porque lo utilizo en un proyecto open source y me interesa que el código este bien internacionalizado, aunque el ingles es muy básico y no cuesta de entenderlo mucho, por supuesto, seguro que el código es mejorable):
Código PHP:
<?
require_once('inc/config.php'); #Load variables of connecction (user,pass,server)
function errorHandler($errno,$errstr,$errfile,$errline)
{ # Handler for user errors as sql or others
switch ($errno)
{
case E_USER_ERROR: # 256
if($errstr=='SQL') #String for sql errors
{
switch(SQL_ERRNO)
{
case '1045': # User or pass or server wrong
echo "Error establishing a database connection";
break;
case '1040': #Too many connections
echo 'Too many connections. Retry in a few seconds.<br>';
break;
case '1203': # more than 'max_user_connections' active connections
echo 'Too many active connections. Retry in a few seconds.<br>';
break;
default: # Others mysql errors
// handling an sql error
echo "<b>SQL Error</b>[".SQL_ERRNO."] ".SQL_ERROR."<br />\n";
echo "Query:".SQL_QUERY."<br />\n";
echo "On line ".SQL_ERROR_LINE." in file ".SQL_ERROR_FILE." ";
echo ", PHP ".PHP_VERSION." (".PHP_OS.")<br />\n";
echo "Aborting...<br />\n";
break;
}
}
else #Others customize errors
{
echo "<b>My ERROR</b> [$errno] $errstr<br />\n";
echo " Fatal error on line $errline in file $errfile";
echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";
echo "Aborting...<br />\n";
}
exit(1);
break;
case E_USER_WARNING:
echo "Error User Warning<br>\n";
break;
case E_USER_NOTICE:
echo "Error User Notice<br>\n";
break;
default:
echo "Error Unknown [$errno]<br>\n";
break;
}
return true; # Don't execute PHP internal error handler
}
function sqlErrorHandler($query='',$php_file,$line)
{ # Handler for sql errors
define("SQL_QUERY",$query);
define("SQL_ERRNO",mysql_errno());
define("SQL_ERROR",mysql_error());
define("SQL_ERROR_LINE",$line);
define("SQL_ERROR_FILE",$php_file);
trigger_error("SQL", E_USER_ERROR);
}
set_error_handler("errorHandler",E_USER_ERROR); # Handler only for user errors
for($i=0;$i<102;$i++)
{
// trigger an sql error
$db[$i] = @mysql_connect($server,$username_mysql,$password_mysql)
or sqlErrorHandler('Try a lot of connections',$_SERVER['PHP_SELF'],__LINE__);
}
sleep(1000);
restore_error_handler();
echo "Done";
?>