Обработка ошибки pdo в php

Ошибки и их обработка

PDO предлагает на выбор 3 стратегии обработки ошибок в зависимости от вашего
стиля разработки приложений.

  • PDO::ERRMODE_SILENT

    До PHP 8.0.0, это был режим по умолчанию. PDO просто предоставит вам код ошибки, который
    можно получить методами PDO::errorCode() и
    PDO::errorInfo(). Эти методы реализованы как в объектах
    запросов, так и в объектах баз данных. Если ошибка вызвана во время выполнения
    кода объекта запроса, нужно вызвать метод
    PDOStatement::errorCode() или
    PDOStatement::errorInfo() этого объекта. Если ошибка
    вызова объекта базы данных, нужно вызвать аналогичные методы у этого объекта.

  • PDO::ERRMODE_WARNING

    Помимо установки кода ошибки PDO выдаст обычное E_WARNING сообщение. Это может
    быть полезно при отладке или тестировании, когда нужно видеть, что произошло,
    но не нужно прерывать работу приложения.

  • PDO::ERRMODE_EXCEPTION

    Начиная с PHP 8.0.0 является режимом по умолчанию. Помимо задания кода ошибки PDO будет выбрасывать исключение
    PDOException, свойства которого будут отражать
    код ошибки и её описание. Этот режим также полезен при отладке, так как
    сразу известно, где в программе произошла ошибка. Это позволяет быстро
    локализовать и решить проблему. (Не забывайте, что если исключение
    является причиной завершения работы скрипта, все активные транзакции
    будут откачены.)

    Режим исключений также полезен, так как даёт возможность структурировать
    обработку ошибок более тщательно, нежели с обычными предупреждениями PHP, а
    также с меньшей вложенностью кода, чем в случае работы в тихом режиме с
    явной проверкой возвращаемых значений при каждом обращении к базе данных.

    Подробнее об исключениях в PHP смотрите в разделе Исключения.

PDO стандартизирован для работы со строковыми кодами ошибок SQL-92 SQLSTATE.
Отдельные драйверы PDO могут задавать соответствия своих собственных кодов
кодам SQLSTATE. Метод PDO::errorCode() возвращает одиночный
код SQLSTATE. Если необходима специфичная информация об ошибке, PDO предлагает
метод PDO::errorInfo(), который возвращает массив, содержащий
код SQLSTATE, код ошибки драйвера, а также строку ошибки драйвера.

Пример #1 Создание PDO объекта и установка режима обработки ошибок


<?php
$dsn
= 'mysql:dbname=testdb;host=127.0.0.1';
$user = 'dbuser';
$password = 'dbpass';$dbh = new PDO($dsn, $user, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);// PDO выбросит исключение PDOException (если таблица не существует)
$dbh->query("SELECT wrongcolumn FROM wrongtable");
?>

Результат выполнения данного примера:

Fatal error: Uncaught PDOException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'testdb.wrongtable' doesn't exist in /tmp/pdo_test.php:10
Stack trace:
#0 /tmp/pdo_test.php(10): PDO->query('SELECT wrongcol...')
#1 {main}
  thrown in /tmp/pdo_test.php on line 10

Замечание:

Метод PDO::__construct() будет всегда бросать исключение PDOException,
если соединение оборвалось, независимо от установленного значения PDO::ATTR_ERRMODE.

Пример #2 Создание экземпляра класса PDO и установка режима обработки ошибок в конструкторе


<?php
$dsn
= 'mysql:dbname=test;host=127.0.0.1';
$user = 'googleguy';
$password = 'googleguy';$dbh = new PDO($dsn, $user, $password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));// Следующий запрос приводит к ошибке уровня E_WARNING вместо исключения (когда таблица не существует)
$dbh->query("SELECT wrongcolumn FROM wrongtable");
?>

Результат выполнения данного примера:

Warning: PDO::query(): SQLSTATE[42S02]: Base table or view not found: 1146 Table 'test.wrongtable' doesn't exist in
/tmp/pdo_test.php on line 9

There are no user contributed notes for this page.

Вернуться к: PDO

PDO предлагает на выбор 3 стратегии обработки ошибок в зависимости от вашего
стиля разработки приложений.

  • PDO::ERRMODE_SILENT

    Это режим по умолчанию. PDO просто предоставит вам код ошибки, который
    можно получить методами PDO::errorCode() и
    PDO::errorInfo(). Эти методы реализованы как в объектах
    запросов так и в объектах баз данных. Если ошибка вызвана во время выполнения
    кода объекта запроса, нужно вызвать метод
    PDOStatement::errorCode() или
    PDOStatement::errorInfo() этого объекта. Если ошибка
    вызова объекта базы данных, нужно вызвать аналогичные методы у этого объекта.

  • PDO::ERRMODE_WARNING

    Помимо задания кода ошибки PDO выдаст обычное E_WARNING сообщение. Это может
    быть полезно при отладке или тестировании, когда нужно видеть, что произошло,
    но не нужно прерывать работу приложения.

  • PDO::ERRMODE_EXCEPTION

    Помимо задания кода ошибки PDO будет выбрасывать исключение
    PDOException, свойства которого будут отражать
    код ошибки и ее описание. Этот режим также полезен при отладке, так как
    сразу известно, где в программе произошла ошибка. Это позволяет быстро
    локализовать и решить проблему. (Не забывайте, что если исключение
    является причиной завершения работы скрипта, все активные транзакции
    будут откачены.)

    Режим исключений также полезен, так как дает возможность структурировать
    обработку ошибок более тщательно, нежели с обычными PHP предупреждениями, а
    также с меньшей вложенностью кода, чем в случае работы в тихом режиме с
    явной проверкой возвращаемых значений при каждом обращении к базе данных.

    Подробнее об исключениях в PHP см. в разделе Исключения.

PDO стандартизирован для работы со строковыми кодами ошибок SQL-92 SQLSTATE.
Отдельные PDO драйверы могут задавать соответствия своих собственных кодов
кодам SQLSTATE. Метод PDO::errorCode() возвращает одиночный
SQLSTATE код. Если необходима специфичная информация об ошибке, PDO предлагает
метод PDO::errorInfo(), который возвращает массив, содержащий
SQLSTATE код, код ошибки драйвера, а также строку ошибки драйвера.

Пример #1 Создание PDO объекта и задание режима обработки ошибок


<?php
$dsn 
'mysql:dbname=testdb;host=127.0.0.1';
$user 'dbuser';
$password 'dbpass';

try {

$dbh = new PDO($dsn$user$password);
    
$dbh->setAttribute(PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION);
} catch (
PDOException $e) {
    echo 
'Подключение не удалось: ' $e->getMessage();
}
?>

Замечание:

Метод PDO::__construct() будет всегда бросать исключение PDOException,
если соединение оборвалось, независимо от установленного значения PDO::ATTR_ERRMODE.
Непойманные исключения фатальны.

Пример #2 Создание экземпляра класса PDO и задание режима обработки ошибок в конструкторе


<?php
$dsn 
'mysql:dbname=test;host=127.0.0.1';
$user 'googleguy';
$password 'googleguy';/*
    По прежнему оберните конструктор в блок try/catch, так как, даже при установке ERRMODE в WARNING,
    PDO::__construct всегда будет бросать исключение PDOException, если соединение оборвалось.
*/
try {
    
$dbh = new PDO($dsn$user$password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING));
} catch (
PDOException $e) {
    echo 
'Соединение оборвалось: ' $e->getMessage();
    exit;
}
// Следующий запрос приводит к ошибке уровня E_WARNING вместо исключения (когда таблица не существует)
$dbh->query("SELECT wrongcolumn FROM wrongtable");
?>

Результат выполнения данного примера:

Warning: PDO::query(): SQLSTATE[42S02]: Base table or view not found: 1146 Table 'test.wrongtable' doesn't exist in
/tmp/pdo_test.php on line 18

Вернуться к: PDO

В этой статье разговор пойдет о PHP Data Objects (PDO) — расширение для PHP, предоставляющее разработчику универсальный интерфейс для доступа к различным базам данных.

В чем преимущество PDO? Этот вопрос можно раскрыть тремя пунктами:

  • Универсальный интерфейс для работы с различными базами данных. Разработчик может легко перевести свое веб-приложение на другую СУБД, поменяв при этом всего пару строк кода.
  • Высокая скорость работы.
  • Подготовленные выражения, о которых мы поговорим чуть позже.

На данный момент расширение PDO может поддерживать СУБД для которой существует PDO-драйвер:

  • PDO_CUBRID (CUBRID)
  • PDO_DBLIB (FreeTDS, Microsoft SQL Server, Sybase)
  • PDO_FIREBIRD (Firebird, Interbase 6)
  • PDO_IBM (IBM DB2)
  • PDO_INFORMIX (IBM Informix Dynamic Server)
  • PDO_MYSQL (MySQL 3.x/4.x/5.x)
  • PDO_OCI (Oracle Call Interface)
  • PDO_ODBC (ODBC v3 (IBM DB2, unixODBC and win32 ODBC))
  • PDO_PGSQL (PostgreSQL)
  • PDO_SQLITE (SQLite 3 and SQLite 2)
  • PDO_SQLSRV (Microsoft SQL Serve )
  • PDO_4D (4D)

Подключение к базе данных

В зависимости от выбранной СУБД, способ подключения может незначительно отличаться. Подключение к популярным СУБД:

// MуSQL
$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); 

// PostgreSQL
$DBH = new PDO("pgsql:host=$host;dbname=$dbname", $user, $pass);

//MS SQL
$DBH = new PDO("mssql:host=$host;dbname=$dbname", $user, $pass); 

// SQLite
$DBH = new PDO("sqlite:my/database/path/database.db");

Обработка ошибок и исключения

Обязательно заключайте подключение к базе данных в блок try/catch:

try {
    $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); 
} 
catch(PDOException $e) { 
    echo "Нет соединения с базой данных"; 
}

Иначе, в случае ошибки, в браузер будет выкинут Fatal error, в котором будут раскрыты все подробности вашего соединения, с логином и паролем.

PDO умеет выбрасывать исключения при ошибках, поэтому все операции с базой, по хорошему, должны находиться в блоке try/catch.

PDO имеет три режима обработки исключения:

  • PDO::ERRMODE_SILENT — режим по умолчанию, ошибки генерируются по такому же принципу, как в расширениях mysql или mysqli. После возникновения ошибки скрипт продолжит работу.
  • PDO::ERRMODE_WARNING — режим вызовет стандартное сообщение E_WARNING и позволит скрипту продолжить работу.
  • PDO::ERRMODE_EXCEPTION — режим выбрасывает исключение, что позволяет обрабатывать ошибки и скрывать важную информацию от посторонних глаз.

Чтобы установить необходимый уровень контроля ошибок необходимо вызвать метод $this->setAttribute после подключения к базе данных.

try {
    $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); 
    $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} 
catch(PDOException $e) { 
    echo "Нет соединения с базой данных"; 
}

Подготовленные выражения или Prepared Statements

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

За подготовленные выражения отвечает метод $DBH->prepare. Им и рекомендуется всегда пользоваться.

Сразу хочу отметить, что выполнить запрос в PDO можно тремя методами:

  • $DBH->exec — используется для запросов, которые не возвращают никаких данных. Метод возвращает количество затронутых им записей, или FALSE в случае ошибки.
$count_row = $DBH->exec("DELETE FROM users");
  • $DBH->query – используется выполнения не защищенных запросов, и возвращает результат или FALSE в случаи ошибки. Например, им можно выполнять простые запросы.
$DBH->query("SET NAMES 'cp1251'");
$DBH->query("SELECT * FROM users");
$DBH->query("DELETE FROM users");
  • $DBH->prepare + $STH->execute — используется для подготовки выражений и выполнения запроса.
// безымянные placeholders
$STH = $DBH->prepare("INSERT INTO users (name, phone, city) values (?, ?, ?)");
// именные placeholders
$STH = $DBH->prepare("INSERT INTO users (name, phone, city) values (:name, :phone, :city)");

После подготовки, запрос выполняется методом $STH->execute($data).

// безымянные placeholders

$data = array();
$data[] = 'Alersander';
$data[] = '+7 000 123 45 67';
$data[] = 'St. Petersburg';

$STH = $DBH->prepare("INSERT INTO users (name, phone, city) values (?, ?, ?)");
$STH->execute($data);
// именные placeholders

$data = array();
$data['name'] = 'Alersander';
$data['phone'] = '+7 000 123 45 67';
$data['city'] = 'St. Petersburg';

$STH = $DBH->prepare("INSERT INTO users (name, phone, city) values (:name, :phone, :city)");
$STH->execute($data);

Выборка данных

Для выборки с произвольными параметрами тоже будем использовать метод $DBH->prepare. Данные выборки можно получить с помощью методов:

  • $STH->fetch — выбирает следующую строку и возвращает в необходимом виде.
  • $STH->fetchAll — возвращает массив всех выбранных строк.
  • $STH->fetchObject — выбирает следующую строку и возвращает ее как объект.

Я буду рассматривать только первый метод, т.к. он универсальный и предоставляет разработчику, всё, что ему необходимо.

Методу $STH->fetch можно указать, в каком виде нам нужно предоставить результат:

  • PDO::FETCH_BOTH (по умолчанию) — возвращает числовой и ассоциативный массив;
  • PDO::FETCH_ASSOC — возвращает массив ассоциативный с названиями столбцов;
  • PDO::FETCH_NUM — возвращает массив числовыми ключами в виде порядковых номеров столбцов;
  • PDO::FETCH_OBJ — возвращает анонимный объект со свойствами, соответствующими именам столбцов;
  • PDO::FETCH_BOUND — присваивает значения столбцов соответствующим переменным, заданным с помощью метода $STH->bindColumn();
  • PDO::FETCH_CLASS — присваивает значения столбцов соответствующим свойствам указанного класса. Если для какого-то столбца свойства нет, оно будет создано;
  • PDO::FETCH_INTO — обновляет существующий экземпляр указанного класса;
  • PDO::FETCH_LAZY — объединяет в себе PDO::FETCH_BOTH и PDO::FETCH_OBJ.
$STH = $DBH->prepare("SELECT name, phone, city FROM users");
$STH->execute();

while($res = $STH->fetch(PDO::FETCH_ASSOC)) {
    echo $res['name'];
}

$STH = $DBH->prepare("SELECT name, phone, city FROM users");
$STH->execute();

while($res = $STH->fetch(PDO::FETCH_OBJ)) {
    echo $res->name;
}

Закрытие соединения и освобождение буфера запроса

В PDO нет специальных методов для этих целей. Закрыть соединение с базой данных можно путем переопределения переменных:

$DBH = null;
$STH = null;

Полезные методы

  • $DBH->lastInsertId() — возвращает id последней вставленной записи.
  • $DBH->query(string) — экранирует специальные символы в строковых данных таким образом, что их становится безопасно использовать в запросах.
  • $STH->rowCount() — возвращает количество затронутых записей последним запросом.

Обработка ошибок PDO

Лично мне не нравится, что если я не заключаю все запросы в блок try/catch, то PDO выкидывает Fatal error со всеми интимными подробностями моего запроса. В промышленном приложении заключать каждый запрос в блок try/catch, это идиотизм!

Поэтому мы поступим следующим образом — немного расширим классы PDO и PDOStatement:

class DB extends PDO
{
    public $error = false; // выводить сообщения об ошибках на экран? (true/false)
    
    public function __construct($dsn, $username='', $password='', $driver_options=array()) {
        try {
            parent::__construct($dsn, $username, $password, $driver_options);
                
            $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('DBStatement', array($this)));
            
            $this->query("SET NAMES 'cp1251'");
        } catch(PDOException $e) { 
            echo "Произошла ошибка в работе с базой данных...";
            exit();
        }
    }
    
    public function prepare($sql, $driver_options=array()) {
        try {
            return parent::prepare($sql, $driver_options);
        } catch(PDOException $e) { 
            $this->error($e->getMessage());
        }
    }
    
    public function query($sql) {
        try {
            return parent::query($sql);
        } catch(PDOException $e) { 
            $this->error($e->getMessage());
        }
    }
    
    public function exec($sql) {
        try {
            return parent::exec($sql);
        } catch(PDOException $e) { 
            $this->error($e->getMessage());
        }
    }
    
    public function error($msg) {
        if($this->error) {
            echo $msg;
        } else {
            echo "Произошла ошибка в работе с базой данных...";
        }
        exit();
    }
}
class DBStatement extends PDOStatement 
{
    protected $DBH;
    
    protected function __construct($DBH) {
        $this->DBH = $DBH;
    }
    
    public function execute($data=array()) {
        try {
            return parent::execute($data);
        } catch(PDOException $e) {
            $this->DBH->error($e->getMessage());
        }
    }
}

Как видите, я реализую свои два класса DB и DBStatement, наследуя классы PDO и PDOStatement. Классы реализуют все необходимые мне для работы над ошибками методы, которые обрабатываются блоком try/catch.

$DBH = new DB("mysql:host=$host;dbname=$dbname", $user, $pass);
$DBH->error = true; // Для отладки выводим сообщения об ошибках на экран.

$STH = $DBH->prepare("SELEC * FROM users");
$STH->execute($data);

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

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; 
check the manual that corresponds to your MySQL server version for the right syntax to use near 
'SELEC * FROM users' at line 1

Расширение функционала

Также бывает полезно расширить функционал PDO. Например, часто требуется получить количество записей в таблице.

Стандартными методами это можно делать следующим образом:

$data = array();
$data['user_id'] = 1;

$STH = $DBH->prepare("SELECT COUNT(*) as count FROM users WHERE user_id=:user_id");
$STH->execute($data);
        
echo $STH->fetch(PDO::FETCH_OBJ)->count;

Не слишком удобно. Поэтому реализуем в нашем классе методом count:

class DB extends PDO
{
    // ..................

    public function count($sql, $data)
    {
        $res = $this->prepare($sql);
        $res->execute($data);
        
        return $res->fetch(PDO::FETCH_OBJ);
    }

    // ..................
}

Получаем количество записей:

$DBH = new DB("mysql:host=$host;dbname=$dbname", $user, $pass);
echo $DBH->count("SELECT COUNT(*) as count FROM users WHERE user_id=:user_id", array('user_id'=>'1'))->count;

Свои методы это конечно хорошо, но мне бы ещё хотелось писать все одной строкой. К сожалению, стандартными возможностями я не могу этого сделать:

$res = $DBH->prepare("SELECT * FROM users WHERE id_user=:id_user")
           ->execute(array('id_user'=>'1'))
           ->fetch(PDO::FETCH_ASSOC);
echo $res['name'];

// или так
echo $DBH->prepare("SELECT *FROM users WHERE id_user=:id_user")
         ->execute(array('id_user'=>'1'))
         ->fetch(PDO::FETCH_OB)
         ->name;

Метод execute возвращает бесполезное логическое значение об успехе операции, а не объект DBStatement.

Допиливаем свой метод execute:

public function execute($data=array())
{
    try {
        parent::execute($data);
        return $this; 
    } 
    catch(PDOException $e) {
        $this->DBH->error($e->getMessage());
    }
}

Проверяем результат:

echo $DBH->prepare("SELECT COUNT(*) as count FROM users WHERE city=:city")
         ->execute(array('city'=>'St. Petersburg'))
         ->fetch(PDO::FETCH_OBJ)
         ->count;

Источник

Каталог оборудования

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Производители

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Функциональные группы

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

That’s a very good question, but there is one wrong premise at the very beginning: you are taking error reporting for PDO separated from site-wide error reporting. Which makes very little sense: PDO errors in every way are the same as other errors — filesystem errors, HTTP errors, and so on. Thus, there is no reason in establishing PDO-only error reporting. All you need is to properly set site-wide error reporting.

There is also one wrong assumption regarding php.ini inaccessibility: you can always set any configuration directive using ini_set() function. Thus, here is not a single reason in setting error_reporting to disastrous level of 0.

To answer the rest of your questions all you need is a little common sense.

A great number of websites say you should echo your error messages in your catch block.
A large number of users on SO say that you should never echo error messages due to security risks.

What you think yourself? Does it any good showing system error messages to user? Does it any good showing system internals to a malicious user?

Others are recommending logging it to a log file outside the document root.

Do you have any objections for this?

Some use error handling to log it to a SQL table.

Don’t you think it’s quite contradicting idea — to log database errors into database?

What is the best practice for handling errors in general in PHP?

You have shown it already: display in dev and log in prod. All is controlled site-wide through few simple configuration options.

What is the best practice for handling errors in the catch-block?

NOT to use try-catch block for error reporting at all. You aren’t going to write a catch block with a friendly error message for the every query in your app, as it’s suggested in the other answer, are you?

Thus your code have to be

<?php
  // Error handling
  error_reporting(-1);
  ini_set('display_errors',0);
  ini_set('log_errors',1);

  // Get credentials from outside document root
  require_once('../settings.php');

  // Tests connection to database
    $dbh = new PDO(
            sprintf(
              'mysql:host=%s;dbname=%s;port=%s;charset=%s',
              $settings['host'],
              $settings['name'],
              $settings['port'],
              $settings['charset']
            ),
            $settings['username'],
            $settings['password']
    );
    // Prevents emulated prepares and activates error handling
    // PDO::ERRMODE_EXCEPTION
    $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Now to the question you voiced in the comment.

A custom error screen is a very different matter and your code is especially bad with it. Neither it should be a 404 error nor an HTTP redirect have to be used (thats very bad for SEO).

To create a custom error page you have to use either your web-server features (preferred) or an error handler in PHP script.

When encountering a fatal error (and uncaught exception is one), PHP responds not with 200 OK HTTP status but with 5xx status. And every web-server can catch this status and show an according error page. E.g. for Apache it would be

ErrorDocument 503 server_error.html

where you can write whatever excuses you want.

Or you can set up a custom error handler in PHP which would handle all PHP errors as well, an example can be seen in the article I wrote on the matter: The (im)proper use of try..catch.

I’m trying to work with PDO class on php but I have some trouble to find the right way to handle errors, I’ve wrote this code:

<?php
// $connection alreay created on a class which works with similar UPDATE statements
// I've simply added here trim() and PDO::PARAM... data type


$id = 33;
$name = "Mario Bros.";
$url = "http://nintendo.com";
$country = "jp";


try {

$sql = "UPDATE table_users SET name = :name, url = :url, country = :country WHERE user_id = :user_id";

$statement = $connection->prepare ($sql);

$statement->bindParam (':user_id', trim($id), PDO::PARAM_INT);
$statement->bindParam (':name', trim($name), PDO::PARAM_STR);
$statement->bindParam (':url', trim($url), PDO::PARAM_STR);
$statement->bindParam (':country', trim($country), PDO::PARAM_STR, 2);

$status = $statement->execute ();

} catch (PDOException $e) {
    print $e->getMessage ();
}

print $status; // it returns a null value, and no errors are reported

?>

this portion of code doesn’t report errors, but it simply doesn’t work, the var $status at the bottom, return a null value.

can someone help me to find where I’m wrong?

Понравилась статья? Поделить с друзьями:
  • Обработка ошибки 404 в php
  • Обработка ошибок в русском языке
  • Обработка запроса провалилась ошибка на этапе первичной обработки документа
  • Обработка ошибок в программе паскаль
  • Обработка запроса провалилась ошибка на этапе обработки документа системой