Деловая неделя

Некоторые сайты не сообщают пользователю об ошибке 404, а «молча» отправляют посетителей на Главную станицу. Надо ли говорить, что такая практика является достаточно стрёмной?

ЕЖЕНЕДЕЛЬНАЯ РЕКЛАМНАЯ ГАЗЕТА ДЛЯ ПРЕДПРИЯТИЙ «Деловая неделя» (Иркутск)

Идеальный фреймворк

Слово «фреймворк» переводится с древне-шумерского как «каркас». Хотя определение «каркас» в случае веб-сайта не очень подходит из-за чрезмерной жёсткости. Серверный фреймворк в веб-программировании работает, скорее, как лекало или трафарет – определяет будущую форму. Или, как рельсы, задаёт направление. Определяет форму и задаёт направление – чему?

Он не должен определять форму страниц сайта – этим занимаются шаблоны. В идеале он не должен также определять и функциональность или жанр сайта – хороший фреймворк может служить основой и для интернет-магазина, и для блога. Фреймворк, прежде всего, определяет структуру программного кода: куда расти, добавлять новые возможности. Например, вспомогательные функции (типа транслита или генерации миниатюр для изображений) можно хранить все вместе в одном файле, а можно в разных файлах, у которых имена должны совпадать с именами классов (в которые должны быть обёрнуты функции).

А ещё серверный фреймворк доложен определять некоторые общие принципы общения с клиентом: например, как обрабатывать УРЛ, если запрошенной странице не соответствует имя реального файла? Считать это сразу ошибкой или пытаться обработать? А если ошибка, то в каком случае выводить её на экран, а в каком игнорировать?

Чаще всего запрос страницы с несуществующим именем файла не является ошибкой: большинство фреймворков отправляют все такие запросы в центральный распределитель – index.php (с помощью соответствующих правил в .htaccess):

Дальше фреймворк пытается по определённым алгоритмам связать запрошенный УРЛ, например, с какой-то информацией в базе данных (и вывести эту информацию на экран). А если алгоритмы приводят к нулевому результату, сообщает об ошибке. Или не сообщает, а «молча» отправляет посетителей на Главную станицу – некоторые фреймворки так делают. Надо ли говорить, что такая практика является стрёмной? Если информации нет, надо возвращать ошибку 404 – это один из важнейших принципов взаимодействия веб-сервера с клиентами. Без этого вы даже не сможете верифицировать сайт в панели Яндекс.Вебмастер (как произошло у нас на одном сайте, изготовленном с помощью «фреймворка» Битрикс). Ясно, что любой фреймворк (даже такой говно-фрейморк, как Битрикс) можно «правильно настроить» с помощью напильника. Так же как и испортить нормальный – положить на «рельсы» кирпич. Но хороший фреймворк должен по умолчанию, изначально задавать направление правильно, качественно (чтобы его можно было испортить, но не было необходимости улучшать).

Что было раньше: курица или яйцо?

Что следует оформить первым: подключение к БД или подключение шаблонов? Наверное, первыми лучше оформить самые простые ответы сервера. Например, "404 страница не найдена". Или "500 Internal server error". Казалось бы, слово «сообщение» (в выражении «сообщение об ошибках») говорит о необходимости подключения шаблона (как без него вывести что-то в браузер?). Но ошибку 500, например, не всегда возможно оформить с участием скрипта PHP. Подключай не подключай шаблоны – до них дело может просто не дойти.

Тем не менее какой-то шаблон всё равно делать надо, иначе некоторые ушлые хостеры тут же без мыла впарят свою рекламу, если самому вовремя не обработать ошибки HTTP. Стандартный минимальный набор (максимально распространённых ошибок) здесь может быть примерно таким: "403 просмотр запрещён", "404 страница не найдена", "500 внутренняя ошибка сервера". Вот для них и надо создать специальные страницы ошибок – прямо в виде HTML-файлов: 403.html, 404.html, 500.html.

Это должны быть именно руками написанные HTML-страницы – не сгенерированные скриптом! Теоретически можно и скриптом (даже в манах Апача так написано), но какой смысл пытаться запустить скрипт, когда, возможно, именно из-за сбоя интерпретатора и появилась ошибка 500? На странице ошибки, в принципе, можно писать всё что угодно, соблюдая стандарты HTML и кодировку, указанную в .htaccess. Например, "Ошибка 404: страница не существует". Ну, и в .htaccess надо не забыть вставить минимальный набор для обработки ошибок:

Вторая строка в этом примере – для возможности вставки на страницу ошибки переменных среды веб-сервера, таких как статус ошибки или адрес главной страницы:

Ошибки PHP

Предположим, сервер пропустил нас к скрипту PHP (не отправил на одну из заготовленных страниц ErrorDocument). Самое важное для дальнейшей работы – видеть все ошибки, порождённые написанным нами кодом. Одна из проблем здесь может быть вызвана настройками в php.ini. Если там стоит display_errors = Off, вы можете не увидеть ошибку. Вы можете написать в начале своего скрипта: display_errors = On, но если ошибка возникнет на уровне распознания кода (parse error), вы её всё равно не увидите, будет просто белая страница. Потому что для срабатывания директивы display_errors = On внутри скрипта, сначала должен быть распознан весь текст скрипта, а именно на этом этапе (распознавания) уже и возникла ошибка, и интерпретатор сдох, не успев осознать, что ошибки-то уже теперь надо выводить на экран.

В некоторых случаях можно поместить директиву отображения ошибок в файл .htaccess:

Но в других случаях (если PHP подключён как CGI) такая директива внутри .htaccess может вызвать ошибку 500. Так что самый надёжный способ – требовать отображения ошибок от php.ini (а внтури скриптов, при необходимости, отключать эту опцию).

Принцип минимальных затрат

При генерации ответов веб-сервер может задействовать больше или меньше ресурсов (процессорного времени, памяти). Например, сгенерировать HTML-страницу с помощью PHP-скрипта будет «дороже», чем отдать готовую страницу (типа ErrorDocument "500.html"). А вытащить информацию для страницы из базы данных – ещё дороже. На разных этапах обработки клиентского запроса используются разные по степени сложности вычислений «модули». На первом этапе обычно разбирается запрос и определяется, какие средства будут нужны для генерации ответа. На втором этапе извлекаются данные из БД. На третьем подключаются шаблоны – файлы с наборами HTML-тэгов и условными метками для вставки данных.

Но ошибки в коде (или при взаимодействии с реальностью) могут появиться на любом этапе работы, и их надо будет как-то отображать. Поэтому хотя бы один шаблон – для отображения ошибок – должен быть подключён уже в самом начале работы. Можно, конечно, обойтись и без шаблона, но тогда отображение ошибок будет происходить именно что «как-то» (некрасиво и недостаточно информативно).

В норме цикл обработки запроса идёт «по большому кругу»: маршрутизатор (анализ УРЛ) – БД – шаблонизатор. Но в случае ошибки должна быть возможность выбросить информацию на экран по короткому пути (но так же качественно, управляемо).

Обработка ошибок PHP (продолжение)

Если ничего в этом плане специально не делать, ошибки будут отображаться примерно так:

Warning: fopen(./errors.txt) [function.fopen]: failed to open stream: Permission denied in /var/www/html/system.php on line 279

Во многих случаях этого бывает вполне достаточно. Но во многих других случаях гораздо удобнее видеть сразу имя пользовательской функции, в которой возникла ошибка, а также ещё и адрес вызываемой страницы. Ну, и желательно, чтобы сообщение об ошибке не расползалось во всю ширину страницы (лучше воспринимается текст шириной 60-70 знаков). Это можно сделать с помощью собственного обработчика ошибок и подходящего шаблона. То есть написать в самом начале обработки запроса примерно следующее:

Здесь пользовательская функция display_error() может выводить сообщение на экран с помощью своего маленького шаблона, или в лог, в зависимости от желания программиста. Полезно ещё бывает добавить к выводу (переменной $err) сведения о цепочке функций, по которой передавался вызов. Что-нибудь вроде:

Здесь debug_backtrace() – родная функция php, а esse() – полезная добавка, позволяющая обращаться к элементам массива, даже если они не существуют:

Фиксируем принципы

Явно или неявно мы опирались в этой статье, главным образом, на три-четыре принципа, которые желательны для фреймворка. Это, конечно, далеко не окончательный набор принципов, это только начало.

1. Принцип экономии ресурсов (или принцип скорости). Веб-сервер по возможности должен отдавать клиентам готовые файлы (а не сгенерированные скриптом): .gif, .jpg, ErrorDocument...

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

3. Принцип «прозрачности» для пользователей сайта. Надо стараться давать ответы клиентам максимально «правдиво»: если страница не существует (запрошенной информации нет), обязательно возвращать ошибку 404 по провилам HTTP-протокола (а не отправлять пользователя на главную страницу).

4. Принцип тотального контроля. Мы хотим управлять всем сами. Мы не можем полагаться на то, что дядя хостер (или сам веб-сервер, «по умолчанию») хорошо обработает ошибки, поэтому мы a) обязательно создаём свои файлы ErrorDocument и б) всеми правдами и неправдами запихиваем в php.ini строку display_errors = On.

D.M., admin

Читать все комментарии (0)

Добавить комментарий:

*Автор:
E-Mail:
*Текст: