PHP 8.1: обработка ошибки с помощью конструкции try-catch

Oct 08, 2022 01:18

Начало: « Windows 10: связываем IIS и PHP с СУБД MySQL».

В предыдущем посте я описал запуск скрипта на языке PHP на локальном веб-сервере IIS из браузера по адресу localhost/testdb.php. Этот скрипт создает соединение с сервером СУБД «MySQL» для возможного получения данных из указанной базы данных:

// mysqli
$mysqli = new mysqli("localhost", "root", "password", "testdb");
$result = $mysqli->query("SELECT 'Привет, дорогой пользователь MySQL!' AS _message FROM DUAL");
$row = $result->fetch_assoc();
echo htmlentities($row['_message']);

У меня при отключенном сервере «mysqld.exe» СУБД «MySQL» этот скрипт возвращает для отображения в браузер следующее сообщение об ошибке:

PHP Fatal error: Uncaught mysqli_sql_exception: Подключение не установлено, т.к. конечный компьютер отверг запрос на подключение in C:\inetpub\wwwroot\testdb.php:3
Stack trace:
#0 C:\inetpub\wwwroot\testdb.php(3): mysqli->__construct('localhost', 'root', 'password', 'testdb')
#1 {main}
thrown in C:\inetpub\wwwroot\testdb.php on line 3

Видно, что сообщение об ошибке браузер отобразил в неправильной кодировке, из-за чего часть сообщения отобразилась кракозябрами (по-английски «mojibake»). В данном случае тело HTTP-ответа пришло в кодировке UTF-8, а браузер отобразил его в кодировке Windows-1252.

Я использую браузер «Microsoft Edge» (на движке «Chromium»), но дело тут не совсем в браузере (хотя и в нем тоже). Тут дело в том, что в данном случае в HTTP-ответе отсутствует HTTP-заголовок «Content-Type», на который обычно ориентируются браузеры при определении кодировки полученного текста. Например, для HTML-страниц этот HTTP-заголовок должен содержать (в большинстве случаев) значение text/html; charset=UTF-8, тогда браузер отобразит полученную HTML-страницу в кодировке UTF-8. (Еще в коде HTML-страниц рекомендуют использовать HTML-элемент , а самое правильное, чтобы и обеспечивался указанный HTTP-заголовок в HTTP-ответе со стороны веб-сервера, и указанный HTML-элемент на передаваемой HTML-странице, то есть оба способа сразу.)

В принципе, сегодня от браузера стоит ожидать, чтобы он по умолчанию (если он не получил ни указанного HTTP-заголовка в HTTP-ответе, ни HTML-элемента на HTML-странице) отображал тексты в кодировке UTF-8, самой распространенной в вебе (97,9 % веб-сайтов на сегодня используют кодировку UTF-8). Но в операционных системах «Windows», к сожалению, до сих пор во главе угла находятся устаревшие кодировки Windows-1251, Windows-1252 и так далее. Так что в отображении вышеприведенных кракозябр есть и вина браузера тоже.

Я несколько дней думал, можно ли как-то добавить в описанном случае в HTTP-ответ нужный HTTP-заголовок со стороны веб-сервера IIS. Перебрал множество возможных способов, но так ничего и не придумал. (Даже написал вопрос на сайте «Stack Overflow», может, кто-нибудь там сможет что-то мне подсказать по этому поводу.)

Можно подойти к этой проблеме немного с другой стороны. В программировании считается неправильным оставлять неотловленные ошибки в программе. В данном случае у нас, как раз, неотловленная (по-английски «uncaught») неустранимая (fatal) ошибка. Такие ошибки обычно отлавливают с помощью известной во многих языках программирования конструкции try..catch, которая есть и в языке PHP. Меняем код:

// mysqli
try {
$mysqli = new mysqli("localhost", "root", "password", "testdb");
$result = $mysqli->query("SELECT 'Привет, дорогой пользователь MySQL!' AS _message FROM DUAL");
$row = $result->fetch_assoc();
echo htmlentities($row['_message']);
} catch (Exception $e) {
echo "
", $e, "";
}

Теперь ошибка отловлена, ход выполнения программы находится у нас под контролем. При этом вывод в браузер ошибки происходит не аварийным, а прописанным в скрипте способом, поэтому используется обычный для языка PHP вывод, при котором в HTTP-ответ вставляется HTTP-заголовок, настраиваемый в файле настроек «php.ini»:

...
default_mimetype = "text/html"
...
default_charset = "UTF-8"
...

То есть нужный HTTP-заголовок Content-Type: text/html; charset=UTF-8 будет сформирован.

Результат в браузере:

mysqli_sql_exception: Подключение не установлено, т.к. конечный компьютер отверг запрос на подключение in C:\inetpub\wwwroot\testdb.php:4
Stack trace:
#0 C:\inetpub\wwwroot\testdb.php(4): mysqli->__construct('localhost', 'root', 'password', 'testdb')
#1 {main}

Видно, что теперь русские буквы выведены корректно. Браузер отобразил текст в нужной кодировке UTF-8.

Инструмент, Образование, Сайтостроение, Программирование, Английский язык

Previous post Next post
Up