Ответ 1
У CI нет хорошей поддержки для исключений. Запросы DB будут вызывать некоторые неопределенные CI error_logging thingy, называемые show_error(). Что вам нужно сделать, это настроить правильную обработку исключений.
В принципе, вы можете следовать всему рецепту.
Теперь все ваши ошибки базы данных будут автоматически генерировать исключения. И в качестве бонуса у вас есть хорошая обработка исключений во всем приложении CI.
Зарегистрируйте настраиваемый обработчик ошибок, который преобразует ошибки PHP в исключения, например, поместите это в начало вашего config/config.php
function my_error_handler($errno, $errstr, $errfile, $errline)
{
if (!(error_reporting() & $errno))
{
// This error code is not included in error_reporting
return;
}
log_message('error', "$errstr @$errfile::$errline($errno)" );
throw new ErrorException( $errstr, $errno, 0, $errfile, $errline );
}
set_error_handler("my_error_handler");
Зарегистрируйте обработчик непрозрачных исключений, добавьте что-то вроде этого в свой config/config.php
function my_exception_handler($exception)
{
echo '<pre>';
print_r($exception);
echo '</pre>';
header( "HTTP/1.0 500 Internal Server Error" );
}
set_exception_handler("my_exception_handler");
Установите обработчик завершения:
function my_fatal_handler()
{
$errfile = "unknown file";
$errstr = "Fatal error";
$errno = E_CORE_ERROR;
$errline = 0;
$error = error_get_last();
if ( $error !== NULL )
{
echo '<pre>';
print_r($error);
echo '</pre>';
header( "HTTP/1.0 500 Internal Server Error" );
}
}
register_shutdown_function("my_fatal_handler");
Установите настраиваемый обработчик assert, который преобразует утверждения в исключения, поместите что-то вроде этого в config/config.php:
function my_assert_handler($file, $line, $code)
{
log_message('debug', "assertion failed @$file::$line($code)" );
throw new Exception( "assertion failed @$file::$line($code)" );
}
assert_options(ASSERT_ACTIVE, 1);
assert_options(ASSERT_WARNING, 0);
assert_options(ASSERT_BAIL, 0);
assert_options(ASSERT_QUIET_EVAL, 0);
assert_options(ASSERT_CALLBACK, 'my_assert_handler');
Используйте в своих контроллерах такие обертки
public function controller_method( )
{
try
{
// normal flow
}
catch( Exception $e )
{
log_message( 'error', $e->getMessage( ) . ' in ' . $e->getFile() . ':' . $e->getLine() );
// on error
}
}
Вы можете настроить и настроить все по своему вкусу!
Надеюсь, что это поможет.
Вам также необходимо перехватить метод CI show_error. Поместите это в application/core/MY_exceptions.php:
class MY_Exceptions extends CI_Exceptions
{
function show_error($heading, $message, $template = 'error_general', $status_code = 500)
{
log_message( 'debug', print_r( $message, TRUE ) );
throw new Exception(is_array($message) ? $message[1] : $message, $status_code );
}
}
И оставьте в приложении /config/database.php этот параметр в FALSE, чтобы ошибки базы данных были преобразованы в исключения.
$db['default']['db_debug'] = TRUE;
CI имеет несколько (очень) слабых точек, таких как обработка исключений, но это будет долго исправлять это.
Если вы собираетесь использовать транзакции, убедитесь, что вы выполняете откаты на исключениях. В связи с этим НИКОГДА (как и в EVER) использование постоянных подключений в качестве открытых транзакций и другого состояния DB для конкретного сеанса будет поднято/продолжено другими сеансами.