Files
php-doc-ru/reference/errorfunc/functions/set-error-handler.xml
2022-04-05 09:28:33 +03:00

385 lines
17 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: 14a60fad6edabd3384c434cc6257255798453e87 Maintainer: tmn Status: ready -->
<!-- Reviewed: no -->
<refentry xml:id="function.set-error-handler" xmlns="http://docbook.org/ns/docbook">
<refnamediv>
<refname>set_error_handler</refname>
<refpurpose>
Задаёт пользовательский обработчик ошибок
</refpurpose>
</refnamediv>
<refsect1 role="description">
&reftitle.description;
<methodsynopsis>
<type class="union"><type>callable</type><type>null</type></type><methodname>set_error_handler</methodname>
<methodparam><type class="union"><type>callable</type><type>null</type></type><parameter>callback</parameter></methodparam>
<methodparam choice="opt"><type>int</type><parameter>error_levels</parameter><initializer><constant>E_ALL</constant></initializer></methodparam>
</methodsynopsis>
<para>
Задаёт пользовательскую функцию (<parameter>callback</parameter>),
как обработчик ошибок в скрипте.
</para>
<para>
Эта функция используется для определения собственного обработчика ошибок
времени выполнения скрипта. Например, если требуется очистить данные/файлы,
когда произошла критическая ошибка, или если нужно переключить тип ошибки,
исходя из каких-то условий (используя функцию
<function>trigger_error</function>).
</para>
<para>
Важно помнить, что стандартный обработчик ошибок PHP не будет обрабатывать
никакие типы ошибок, определённые в <parameter>error_levels</parameter>,
пока callback-функция не вернёт &false;. Пользовательский обработчик будет
вызываться при любой ошибке, независимо от настроек, заданных функцией
<link linkend="ini.error-reporting">error_reporting</link>.
</para>
<para>
Также важно помнить, что на совести обработчика лежит вызов функции
<function>die</function> в случае необходимости. Если происходит возврат
из обработчика ошибок, управление передаётся следующему выражению,
стоящему за тем, что вызвало ошибку.
</para>
<para>
Ошибки следующих типов не могут быть обработаны пользователем:
<constant>E_ERROR</constant>, <constant>E_PARSE</constant>,
<constant>E_CORE_ERROR</constant>, <constant>E_CORE_WARNING</constant>,
<constant>E_COMPILE_ERROR</constant>,
<constant>E_COMPILE_WARNING</constant> независимо от того, где они были сгенерированы и большинство
ошибок <constant>E_STRICT</constant>, произошедших в файле, где вызвана
функция <function>set_error_handler</function>.
</para>
<para>
Если ошибки возникают до запуска скрипта (например, пока файл загружается),
пользовательский обработчик не будет вызываться, если на этот момент он
ещё не зарегистрирован.
</para>
</refsect1>
<refsect1 role="parameters">
&reftitle.parameters;
<para>
<variablelist>
<varlistentry>
<term><parameter>callback</parameter></term>
<listitem>
<para>
Если передано значение &null;, обработчик сбрасывается в состояние по умолчанию.
В противном случае обработчик представляет собой callback-функцию со следующей сигнатурой:
</para>
<para>
<methodsynopsis>
<type>bool</type><methodname><replaceable>handler</replaceable></methodname>
<methodparam><type>int</type><parameter>errno</parameter></methodparam>
<methodparam><type>string</type><parameter>errstr</parameter></methodparam>
<methodparam choice="opt"><type>string</type><parameter>errfile</parameter></methodparam>
<methodparam choice="opt"><type>int</type><parameter>errline</parameter></methodparam>
<methodparam choice="opt"><type>array</type><parameter>errcontext</parameter></methodparam>
</methodsynopsis>
<variablelist>
<varlistentry>
<term><parameter>errno</parameter></term>
<listitem>
<simpara>
В первый аргумент <parameter>errno</parameter> будет передан уровень
ошибки в виде целого числа.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>errstr</parameter></term>
<listitem>
<simpara>
Во второй аргумент <parameter>errstr</parameter> будет передано сообщение
об ошибке в виде строки.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>errfile</parameter></term>
<listitem>
<simpara>
Если функция обратного вызова принимает третий параметр
<parameter>errfile</parameter>, то в него будет передано
имя файла, в котором произошла ошибка, в виде строки.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>errline</parameter></term>
<listitem>
<simpara>
Если функция обратного вызова принимает четвёртый параметр
<parameter>errline</parameter>, то в него будет передан
номер строки, в которой произошла ошибка, в виде целого
числа.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>errcontext</parameter></term>
<listitem>
<simpara>
Если функция обратного вызова принимает пятый параметр
<parameter>errcontext</parameter>, то в него будет передан
массив указателей на активную таблицу символов в точке, где
произошла ошибка. Другими словами, <parameter>errcontext</parameter>
будет содержать массив всех переменных, существующих в области
видимости, где произошла ошибка. Пользовательские обработчики ошибок не
должны изменять этот контекст.
</simpara>
<warning xmlns="http://docbook.org/ns/docbook">
<simpara>
Этот параметр объявлен <emphasis>УСТАРЕВШИМ</emphasis> начиная с PHP 7.2.0 и
был <emphasis>УДАЛЁН</emphasis> в PHP 8.0.0. Если в вашей функции этот
параметр используется и для него не задано значение по умолчанию, то при
вызове функции обработчика будет выдана ошибка "too few arguments".
</simpara>
</warning>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Если функция возвращает &false;, управление передаётся встроенному
обработчику ошибок.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>error_levels</parameter></term>
<listitem>
<para>
Может использоваться для задания маски, в соответствии с которой будет
вызываться <parameter>callback</parameter>, по аналогии с
ini-настройкой <link linkend="ini.error-reporting">error_reporting</link>,
которая отвечает за то, какие ошибки будут показаны в отчёте. Без этой
маски <parameter>callback</parameter> будет вызываться для
обработки всех происходящих ошибок, вне зависимости от настроек в
<link linkend="ini.error-reporting">error_reporting</link>.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</refsect1>
<refsect1 role="returnvalues">
&reftitle.returnvalues;
<para>
Возвращает ранее определённый обработчик ошибок (если есть) Если на данный момент используется встроенный обработчик, функция
вернёт &null;. Если предыдущий определённый обработчик является методом класса, функция вернёт массив,
содержащий имя класса и имя метода.
</para>
</refsect1>
<refsect1 role="changelog">
&reftitle.changelog;
<para>
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry>&Version;</entry>
<entry>&Description;</entry>
</row>
</thead>
<tbody>
<row>
<entry>8.0.0</entry>
<entry>
Параметр <parameter>errcontext</parameter> был удалён и больше не передаётся в
пользовательскую функцию обработки ошибок.
</entry>
</row>
<row>
<entry>7.2.0</entry>
<entry>
Параметр <parameter>errcontext</parameter> объявлен устаревшим. Теперь при его
использовании будет вызываться ошибка уровня <constant>E_DEPRECATED</constant>.
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</refsect1>
<refsect1 role="examples">
&reftitle.examples;
<para>
<example>
<title>
Обработка ошибок с помощью функций <function>set_error_handler</function>
и <function>trigger_error</function>
</title>
<para>
Пример ниже демонстрирует обработку внутренних исключений путём
вызова ошибок разных типов и их обработки пользовательской функцией:
</para>
<programlisting role="php">
<![CDATA[
<?php
// функция обработки ошибок
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
if (!(error_reporting() & $errno)) {
// Этот код ошибки не включён в error_reporting,
// так что пусть обрабатываются стандартным обработчиком ошибок PHP
return false;
}
// может потребоваться экранирование $errstr:
$errstr = htmlspecialchars($errstr);
switch ($errno) {
case E_USER_ERROR:
echo "<b>Пользовательская ОШИБКА</b> [$errno] $errstr<br />\n";
echo " Фатальная ошибка в строке $errline файла $errfile";
echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";
echo "Завершение работы...<br />\n";
exit(1);
case E_USER_WARNING:
echo "<b>Пользовательское ПРЕДУПРЕЖДЕНИЕ</b> [$errno] $errstr<br />\n";
break;
case E_USER_NOTICE:
echo "<b>Пользовательское УВЕДОМЛЕНИЕ</b> [$errno] $errstr<br />\n";
break;
default:
echo "Неизвестная ошибка: [$errno] $errstr<br />\n";
break;
}
/* Не запускаем внутренний обработчик ошибок PHP */
return true;
}
// функция для тестирования обработчика ошибок
function scale_by_log($vect, $scale)
{
if (!is_numeric($scale) || $scale <= 0) {
trigger_error("log(x) для x <= 0 не определён, вы используете: scale = $scale", E_USER_ERROR);
}
if (!is_array($vect)) {
trigger_error("Некорректный входной вектор, пропущен массив значений", E_USER_WARNING);
return null;
}
$temp = array();
foreach($vect as $pos => $value) {
if (!is_numeric($value)) {
trigger_error("Значение на позиции $pos не является числом, будет использован 0 (ноль)", E_USER_NOTICE);
$value = 0;
}
$temp[$pos] = log($scale) * $value;
}
return $temp;
}
// переключаемся на пользовательский обработчик
$old_error_handler = set_error_handler("myErrorHandler");
// вызовем несколько ошибок, во-первых, определим массив с нечисловым элементом
echo "vector a\n";
$a = array(2, 3, "foo", 5.5, 43.3, 21.11);
print_r($a);
// теперь создадим ещё один массив
echo "----\nvector b - a notice (b = log(PI) * a)\n";
/* Значение на позиции $pos не является числом, будет использован 0 (ноль)*/
$b = scale_by_log($a, M_PI);
print_r($b);
// проблема, мы передаём строку вместо массива
echo "----\nvector c - a warning\n";
/* Некорректный входной вектор, пропущен массив значений */
$c = scale_by_log("not array", 2.3);
var_dump($c); // NULL
// критическая ошибка, логарифм от неположительного числа не определён
echo "----\nvector d - fatal error\n";
/* log(x) для x <= 0 не определён, вы используете: scale = $scale */
$d = scale_by_log($a, -2.5);
var_dump($d); // До сюда не дойдём никогда
?>
]]>
</programlisting>
&example.outputs.similar;
<screen>
<![CDATA[
vector a
Array
(
[0] => 2
[1] => 3
[2] => foo
[3] => 5.5
[4] => 43.3
[5] => 21.11
)
----
vector b - a notice (b = log(PI) * a)
<b>Пользовательское УВЕДОМЛЕНИЕ</b> [1024] Значение на позиции 2 не является числом, будет использован 0 (ноль)<br />
Array
(
[0] => 2.2894597716988
[1] => 3.4341896575482
[2] => 0
[3] => 6.2960143721717
[4] => 49.566804057279
[5] => 24.165247890281
)
----
vector c - a warning
<b>Пользовательское ПРЕДУПРЕЖДЕНИЕ</b> [512] Некорректный входной вектор, пропущен массив значений<br />
NULL
----
vector d - fatal error
<b>Пользовательская ОШИБКА</b> [256] log(x) for x <= 0 is undefined, you used: scale = -2.5<br />
Фатальная ошибка в строке 35 файла trigger_error.php, PHP 5.2.1 (FreeBSD)<br />
Завершение работы...<br />
]]>
</screen>
</example>
</para>
</refsect1>
<refsect1 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member><classname>ErrorException</classname></member>
<member><function>error_reporting</function></member>
<member><function>restore_error_handler</function></member>
<member><function>trigger_error</function></member>
<member><link linkend="errorfunc.constants">Константы уровней ошибок</link></member>
</simplelist>
</para>
</refsect1>
</refentry><!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->