Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Обработка ошибок через возвращаемые значения


Автор: Ripper 12.9.2012, 13:48
Добрый день.
Насколько я понял, есть 2 метода обработки ошибок - исключения и возвращаемые значения. Исключения на php я никогда не использовал, так сложилось. Более привычно вернуть из функции true/false.
Только вопрос в том, что, когда нужно разделять несколько видов ошибок, какого типа данные вы возвращаете из ф-ии?
цифру (1 - запись прошла успешна, 2 - не найден id, 3 - ..), строку ("success", "id_not_found") или может массив  ('status'=>'error', 'errorType'=>...)?
Как правильно действовать в этой ситуации?) 
Спасибо

Автор: baldina 12.9.2012, 14:33
всё зависит от ситуации. где-то вообще достаточно вернуть false, где-то нужна подробная информация. возвращать строки имхо странно.
Цитата(Ripper @  12.9.2012,  13:48 Найти цитируемый пост)
когда нужно разделять несколько видов ошибок

тогда и начинаешь понимать зачем исключения
...
информация об ошибке нужна что бы
1. проанализировать и принять решение в программе
2. выдать соответствующее сообщение

сложившаяся разумная практика (не только в php, вообще) - иметь числовые коды ошибок и строковые сообщения. дабы сделать обработку кода ошибки понятней, можно определить константы, имеющие осмысленные имена
Код

define ('NO_ERROR',0); 
define ('RECORD_NOT_FOUND',1);
...
$errmsg = array (NO_ERROR=>'',RECORD_NOT_FOUND=>'Запись не найдена'...)

Автор: Ripper 12.9.2012, 14:55
Опишу ситуацию по-подробнее.
Я использую сейчас CodeIgniter. У меня есть на сайте кнопка, которая устанавлиавает значение для сущности в БД. Ну скажем, наценка на товар.
Делается это через аякс. Клиент отправляет запрос, получает ответ и в зависимости от ответа что-то выводит, типа "Наценка успешно изменена", или "Произошла ошибка". Но существует например еще такая ошибка - наценку нельзя изменить если не установлена базовая стоимость. И еще ошибка - не найдена запись в БД по такому то id.

Соотвественно есть класс модели с ф-ией изменения наценки, есть контроллер котороый вызывает ф-ию в модели и парсит результат. А дальше уже отдает юзеру в нужном ему формате окончательный результат.

Я понимаю что строки возвращать как -то странно, хотя вроде очень удобно ? (return "id_not_found" и вроде все, можно проверять в контроллере)

т.е. мне нужно в конфиге описать общие defin-ы для всех ошибок, далее возвращать из ф-ии этот дефайн , а в контроллере свитчить результат по дефайнам? Вообще странно, зачем тогда нужны значения дефайнам в принципе. Я же их все равно никогда не использую

Похоже пора почитать про исключения)

Автор: Ripper 12.9.2012, 15:25
http://blog.voltampmedia.com/2011/12/08/php-exceptions-and-codeigniter/ собственно вот моя ситуация
но если я верно понял, то ошибка типа "запись не найдена" это не исключение, а просто один из возможных результатов, и для этого исключения применять не надо

Автор: baldina 12.9.2012, 16:39
возможно, в данном случае и без исключений все красиво.

Цитата(Ripper @  12.9.2012,  14:55 Найти цитируемый пост)
т.е. мне нужно в конфиге описать общие defin-ы для всех ошибок, далее возвращать из ф-ии этот дефайн , а в контроллере свитчить результат по дефайнам? Вообще странно, зачем тогда нужны значения дефайнам в принципе. Я же их все равно никогда не использую

да, так. а насчет "никогда не использую" не согласен: они используются в момент выставления ошибки:

Код

define ('ERROR_SUCCESS',0);
define ('ERROR_SELECT',1);
define ('ERROR_UPDATE',2);
define ('ERROR_EMPTY_BASE_PRICE',3);

class Model {
  function applyMarkUp ($id, $value) {
     $data = get_record ($id);
     if (!$data)
       return ERROR_SELECT;

     if (!$data->base_price)
       return ERROR_EMPTY_BASE_PRICE;

     $data->base_price += $value;
     if (put_record ($id, $data))
       return ERROR_SUCCESS;
    else
       return ERROR_UPDATE;
  }
}

class Error {
 static private $errmsg = array (
   ERROR_SUCCESS=>'Наценка успешно изменена'
  ,ERROR_SELECT=>'Запись не найдена'
  ,ERROR_UPDATE=>'Ошибка обновления записи'
  ,ERROR_EMPTY_BASE_PRICE=>'Не определена базовая цена'
 );

 static function get_message ($error) {
    return $this->errmsg[$error];
 }
}

class Controller {
  function MarkUpAction () {
    $model = new Model();
    $status = $model->applyMarkUp ($query['id'], $query['value']);
    echo Error::get_message ($status);
  }
}


с исключениями было бы покороче
Код

define ('ERROR_SELECT',1);
define ('ERROR_UPDATE',2);
define ('ERROR_EMPTY_BASE_PRICE',3);

class MarkUpException extends Exception {
 static private $errmsg = array (
   ERROR_SELECT=>'Запись не найдена'
  ,ERROR_UPDATE=>'Ошибка обновления записи'
  ,ERROR_EMPTY_BASE_PRICE=>'Не определена базовая цена'
 );

 function __construct ($code) {
    parent::__construct(self::$errmsg[$code], $code);
 }
}

class Model {
  function applyMarkUp ($id, $value) {
     $data = get_record ($id); // can throw exception
     if (!$data->base_price)
       throw new MarkUpException (ERROR_EMPTY_BASE_PRICE);

     $data->base_price += $value;
     put_record ($id, $data); // can throw exception
  }
}

class Controller {
  function MarkUpAction () {
    try {
      $model = new Model();
      $status = $model->applyMarkUp ($query['id'], $query['value']);
      echo 'Наценка успешно изменена';
    } catch (MarkUpException $ex) {
      echo $ex->getMessage ();
   }
  }
}


Автор: Ripper 12.9.2012, 22:56
А еще вопрос, вот как сделано сейчас: я возвращаю клиенту строку типа {status:error, errorType: record_not_found}, а он в js коде уже выводит на русском сообщение. Если я правильно понял такая практика не правильная, и нужно отправлять сообщение с сервера?

Дело в том что мне нужна будет языковая поддержка. в CI вместо дефайнов я могу использовать языковые переменные, там есть специальный файлик в котором содержатся строки типа:
Код

$lang['DB_ERROR'] = 'db error message';


Соотвественно я решил сделать так:
Код

$lang['prefix_errors'] = array(DB_RECORD_NOT_FOUND => 'record not found');

это английский перевод, для русского точно такой же файлик уже с русским переводом

В контроллере:
Код

    private function getError($error) {
        return element($error, $this->lang->line('prefix_errors'));
    }

Все вроде хорошо. Единственное что - верно ли отправлять с сервера строку с ошибкой, или её нужно формировать в js? (Что, впрочем, я не знаю как делать совершенно)

Автор: baldina 13.9.2012, 01:02
Цитата(Ripper @  12.9.2012,  22:56 Найти цитируемый пост)
верно ли отправлять с сервера строку с ошибкой

в Вашем случае верно

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)