У меня есть unique
ограничение для столбца. Когда этот код работает, я получаю журнал ошибок из фреймворка, но это не то, что я дал в блоке исключений.
Если существует уникальный столбец, я хочу запросить его первичный ключ и установить его как $id
и вернуться на страницу. Сейчас он останавливается на ошибке db и не входит в Catch block
.
Вот мой код:
try { $result = $this->db->insert('email', $new_email); if ($result) { $id = $this->db->insert_id(); } else { throw new Exception("$$$$$$$$$$$$$Log database error"); } } catch (Exception $e) { log_message('error',$e->getMessage()); return; }
**Error Messages**
Я получаю из фреймворка:
DEBUG - 2013-04-07 05:00:38 --> DB Transaction Failure ERROR - 2013-04-07 05:00:38 --> Query error: Duplicate entry
Я не знаю, что с ним не так.
У 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 ); } }
И оставить в application / config / database.php этот параметр в FALSE, чтобы ошибки базы данных были преобразованы в исключения.
$db['default']['db_debug'] = TRUE;
У CI есть несколько (очень) слабых мест, таких как обработка исключений, но это будет долго исправлять это.
Если вы собираетесь использовать транзакции, убедитесь, что вы выполняете откаты на исключениях. В связи с этим НИКОГДА (как и в EVER) использование постоянных подключений в качестве открытых транзакций и другого состояния DB для конкретного сеанса будет поднято / продолжено другими сеансами.
Если включена отладка базы данных, ошибки из БД будут перенаправлены в основной класс Исключения, а exit()
вызывается после, что означает, что сценарий никогда не достигнет вашего условного условия if
.
Откройте application/config/database.php
и попробуйте установить db_debug
на false. Это хорошая идея для создания веб-сайтов, так или иначе, потому что вы не хотите, чтобы какие-либо проблемы с SQL-запросом вывела информацию о вашей структуре базы данных.
Кроме того, не связанный с этим, будьте осторожны, используя $
внутри двойных кавычек, потому что он будет анализироваться как переменная (даже куча из них в строке – это будет буквально переменная переменная переменная …).
Что делать, если вы устанавливаете результат вне блока try
? Или тройной оператор:
$result = $this->db->insert('email', $new_email); try { $result = ($result) ? $result || false; if ($result) { $id = $this->db->insert_id(); } else { throw new Exception("$$$$$$$$$$$$$Log database error"); } } catch (Exception $e) { log_message('error',$e->getMessage()); return; }
Трудно понять, не зная, какова ценность $result
, как, например, @jcorry.