Главная > Программирование > РНР: настольная книга программиста
<< Предыдущий параграф
Следующий параграф >>
<< Предыдущий параграф Следующий параграф >>
Макеты страниц

Часть III. Особенности реализации языка

Глава 16. Обработка ошибок в PHP

Данная глава написана для того, чтобы вы смогли понять систему определения ошибок в РНР. Прежде всего познакомимся с основными типами ошибок, а также как с ними бороться. Не зная эту главу, вы без труда сможете освоить язык, но в случае возникновения каких-либо неприятностей обращайтесь к этой главе. В ней рассматриваются следующие темы:

• типы ошибок и предупреждений об ошибках;

• подавление ошибок при обращении к функциям.

16.1. Типы ошибок и предупреждений об ошибках

В РНР имеется несколько типов ошибок и предупреждений об ошибках (табл. 16.1).

Таблица 16.1. Типы ошибок РНР

Перечисленные выше значения (числовые или символьные) используются для построения битовой маски, определяющей ошибку, о которой выдается сообщение. Для комбинации значений или определенных типов ошибок можно использовать побитовые операторы. Но обратите внимание на то, что в php. ini будут восприниматься только |, ! и &, а в php3.ini побитовые операторы восприниматься не будут.

В РНР 4 значением по умолчанию для параметра error_reporting является E_ALL & ~E_NOTICE, что означает отображение всех сообщений об ошибках и предупреждений, не имеющих уровня E_NOTICE. В РНР 3 по умолчанию используется значение E_ERROR | E_WARNING | E_PARSE, что означаетто же самое. Однако обратите внимание, что, поскольку в php3.ini в РНР 3 константы не поддерживаются, установка error_reporting должна быть числовой (например, 7).

Начальную установку можно изменить в файле ini с помощью директивы error_reporting в файле httpd.conf Apache с помощью директивы php_error_reporting (php3_error_reporting для РНР 3), а также во время выполнения в скрипте с помощью функции error_reporting().


ВНИМАНИЕ

При обновлении кода или серверов с РНР 3 на РНР 4 следует проверить эти установки и вызовы error_reporting(), иначе можно отключить сообщение об ошибках новых типов, особенно E_COMPILE_ERROR. Это может привести к выдаче пустых документов вместо сообщения о происходящем или информации о том, где нужно искать проблему.


Все выражения РНР могут также вызываться с префиксом @, отключающим сообщения об ошибкахдля данного конкретного выражения. Если к таком выражении происходит ошибка, и функция track_errors активна, сообщение об ошибке можно будет найти в глобальной переменной $php_errormsg.

Префикс @ оператора контроля ошибок не отключает сообщения, возникающие в результате синтаксического анализа.


ВНИМАНИЕ

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


Рассмотрим пример использования возможностей обработки ошибок в РНР. Определим функцию для обработки ошибок, которая будет протоколировать информацию в файл (используя формат XML) и отправлять его разработчику по электронной почте в случае критической ошибки в логике.

Пример 16.1. Обработка ошибок в скрипте

<?php

// будем сами обрабатывать ошибки

error_reporting(0);

// определенная пользователем функция обработки ошибок

function userErrorHandler($errno, $errmsg, $filename, $linenum, $vars) {

    // дата и время записи об ошибке

    $dt = date("Y-m-d ,H:i:s (T)");

    // определение ассоциативного массива строк ошибок

    // на самом деле следует рассматривать

    // только элементы 2, 8, 256, 512 и 1024

    $errortype = array (    1 => "Ошибка",

    2 => "Предупреждение",

    4 => "Сшибка синтаксического анализа",

    8 => "Замечание",

    16 => "Сшибка ядра",

    32 => "Предупреждение ядра",

    64 => "Сшибка компиляции",

    128 => "Предупреждение компиляции",

    256 => "Сшибка пользователя",

    512 => "Предупреждение пользователя",

    1024 => "Замечание пользователя"

    );

    // набор ошибок, для которого будут сохраняться значения переменных

    $user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);

    $err = "<errorentry>\n";

    $err .= "\t<datetime>".$dt."</datetime>\n";

    $err .= "\t<errornum>" . $errno. "</errnumber>\n" ;

    $err .= "\t<errortype>".$errortype[$errno]."</errortype>\n";

    $err .= "\t<errormsg>".$errmsg."</errormsg>\n";

    $err .= "\t<scriptname>".$filename."</scriptname>\n";

    $err .= "\t<scriptlinenum>".$linenum."</scriptlinenum>\n";

    if (in_array($errno, $user_errors))

        $err .= "\t<vartrace>".wddx_serialize_value($vars, "Variables")."</ vartrace>\n";

    $err .= "</errorentry>\n\n";

    // для тестирования

    // echo $err;

    // сохранить протокол ошибок и отправить его мне,

    // если есть критические ошибки

    error_log($err, 3, "/usr/local/php4/error.log");

    if ($errno == E_USER_ERROR)

        mail("phpdev@mydomain.com", "Critical User Error",$err);}

function distance($vect1, $vect2) {

    if (!is_array($vect1) || !is_array($vect2)) {

        trigger_error("Incorrect parameters, arrays expected", E_USER_ERROR);

        return NULL;

    }

    if (count($vect1) ! = count($vect2)) {

        trigger_error("Vectors need to be of the same size", E_JJSER_ERROR);

        return NULL;

    }

    for ($i=0; $i<count($vectl); $i++) {

        $c1 = $vectl[$i];

        $c2 = $vect2[$i];

        $d = 0.0;

        if(!is_numeric($c1)) {

            trigger_error("Coordinate $i in vector 1 is not a number, using , zero", E_USER_WARNING);

            $c1 = 0.0;

        }

        if (!is_numeric($c2)) {

            trigger_error("Coordinate $i in vector 2 is not a number using zero", E_USER__WARNING);

            $c2 = 0.0;

        }

        $d += $c2*$c2 - $c1*$c1;

    }

    return sqrt($d);

}

$old_error_handler = set_error_handler("userErrorHandler");

// неопределенная константа генерирует предупреждение

$t = I_AM__NOT_DEFINED;

// определение некоторых "векторов"

$а = array(2,3,"foo");

$b = array(5.5, 4.3, -1.6);

$c = array (1,-3);

// генерация пользовательской ошибки

$t1 = distance ($c, $b) ."\n";

// генерация другой пользовательской ошибки

$t2 = distance($b,"i am not an array") ,"\n";

// генерация предупреждения

$t3 = distance($a,$b),"\n";

?>

Это всего лишь простой пример, демонстрирующий использование функций обработки и протоколирования ошибок.

<< Предыдущий параграф Следующий параграф >>
Оглавление