Подтвердить что ты не робот

CodeIgniter: Try Catch не работает в классе модели

У меня есть ограничение 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 

Я не знаю, что с ним не так.

4b9b3361

Ответ 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 для конкретного сеанса будет поднято/продолжено другими сеансами.

Ответ 2

Если отладка базы данных включена, ошибки из БД будут перенаправлены в основной класс Исключения, а exit() вызывается после, что означает, что script никогда не достигнет вашего условного условия if.

Откройте application/config/database.php и попробуйте установить db_debug на значение false. Это хорошая идея для создания веб-сайтов, так или иначе, потому что вы не хотите, чтобы какие-либо проблемы с SQL-запросом выставляли информацию о вашей структуре базы данных.

Кроме того, не связанный, будьте осторожны с использованием $ внутри двойных кавычек, потому что он будет анализироваться как переменная (даже куча из них в строке - это будет буквально переменная переменная переменная..).

Ответ 3

Что делать, если вы устанавливаете результат вне блока 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.