Вчера всё работало, а сегодня не работает / Код не работает как задумано
или
Debugging (Отладка)
В чем заключается процесс отладки? Что это такое?
Процесс отладки состоит в том, что мы останавливаем выполнения скрипта в любом месте, смотрим, что находится в переменных, в функциях, анализируем и переходим в другие места; ищем те места, где поведение отклоняется от правильного.
Важное замечание:
Есть много IDE и редакторов кода, которые позволяют производить отладку. Процесс настройки в них у всех различается. Поэтому стОит обратиться к документации по настройке отладки для непосредственно той среды разработки и той версии, в которой работаете именно ВЫ.
На текущий момент будет рассмотрен пример с PHPStorm 2017.
Подготовка
Для начала необходимо, чтобы в PHP имелась библиотека для отладки под названием xdebug. Если её еще нет, то надо установить.
ВАЖНО! Для очень новых версий PHP (например 8), требуется и новый xdebug
, а он, в свою очередь, работает на порту 9003. Не пропустите указание правильного порта в IDE!! (Примерно в разделе PHP -> Debug -> Debug Port . Где точно – зависит от конкретной IDE)
Для WINDOWS:
скачать dll, например на xdebug.org.
Обычно все библиотеки лежат в папке ext
внутри папки PHP. Туда и надо поместить dll
.
Далее в php.ini
прописываем настройки:
[Xdebug]
zend_extension="C:/server/php/ext/php_xdebug.dll" // <!-- тут свой путь до dll!!! Это для среды Windows.
; Для Linux путь должен быть что-то типа zend_extension=/usr/lib/php/20151012/xdebug.so
xdebug.default_enable = 1
xdebug.remote_enable = 1
xdebug.remote_handler = "dbgp"
xdebug.remote_host = "localhost"
xdebug.remote_port = 9000
xdebug.auto_trace = 0
Перезагружаем сервер, на всякий случай.
Для UBUNTU:
-
sudo apt update
ИЛИsudo apt-get update
-
sudo apt install php-xdebug
или если нужнен отладчик для конкретной версии PHP, тоsudo apt install php7.0-xdebug
где7.0
указывается версия PHP -
sudo nano /etc/php/7.0/mods-available/xdebug.ini
вписываем строки:
zend_extension=/usr/lib/php/20151012/xdebug.so xdebug.remote_autostart = 1 xdebug.remote_enable = 1 xdebug.remote_handler = dbgp xdebug.remote_host = 127.0.0.1 xdebug.remote_log = /tmp/xdebug_remote.log xdebug.remote_mode = req
Примечание: каталог
20151012
, скорее всего, будет другим.cd
в/usr/lib/php
и проверьте, в каком каталоге в этом формате находится файлxdebug.so
, и используйте этот путь.7.0
– тоже отличается, в зависимости от того, какая версия у вас используется -
Перезагружаем сервер, на всякий случай.
Теперь если в файле .php
написать phpinfo();
то можно будет увидеть в самом низу такую картину:
Открываем PHPStorm
- нажимаем
create project from existing files
- выбираем
Web server is installed locally, source files are located under its document root
- выбираем папку с файлами, и нажав вверху кнопку “Project Root” помечаем папку как корень проекта
- нажимаем “Next”
- нажимаем Add new local server
- вводим имя сервера любое и
Web Server root URL
. В рассматриваемом примере этоhttp://localhost/testy2
- нажимаем “Next” и затем “Finish”
Запуск
Для начала в левой части панели с кодом на любой строке можно кликнуть ЛКМ, тем самым поставив точку останова (breakpoint – брейкпойнт). Это то место, где отладчик автоматически остановит выполнение PHP, как только до него дойдёт. Количество breakpoint’ов не ограничено. Можно ставить везде и много.
Если кликнуть ПКМ и во всплывающем меню выбрать Debug
(или в верхнем меню – Run
→ Debug
), то при первом запуске PHPStorm попросит настроить интерпретатор. Т.е. надо выбрать версию PHP из папки, где он лежит, чтобы шторм знал, какую версию он будет отлаживать.
Теперь можно нажать Debug
!!!
В данном случае, т.к. функция вызывается сразу на той же странице, то при нажатии кнопки Debug
— отладчик моментально вызовет функцию, выполнение “заморозится” на первом же брейкпойнте. В ином случае, для активации требуется исполнить действие, при котором произойдет исполнение нужного участка кода (клик на кнопку, передача POST-запроса с формы с данными и другие действия).
Цифрами обозначены:
- Стэк вызовов, все вложенные вызовы, которые привели к текущему месту кода.
- Переменные. На текущий момент строки ниже номера 3 ещё не выполнились, поэтому определена лишь
$data
- Показывает текущие значения любых переменных и выражений. В любой момент здесь можно нажать на
+
, вписать имя любой переменной и посмотреть её значение в реальном времени. Например:$data
или$nums[0]
, а можно и$nums[i]
иitem['test']['data'][$name[5]][$info[$key[1]]]
и т.д. На текущий момент строки ниже номера 3 ещё не выполнились, поэтому$sum
и$output
обозначены красным цветом с надписью “cannot evaluate expression”.
Процесс
Для самого процесса используются элементы управления (см. изображение выше, выделено зеленым прямоугольником) и немного из дополнительно (см. изображение выше, выделено оранжевым прямоугольником).
Show Execution Point (Alt+F10) — переносит в файл и текущую линию отлаживаемого скрипта. Например, если файлов много, решили посмотреть что в других вкладках, а потом забыли где у вас отладка 🙂
Step Over (F8) — делает один шаг, не заходя внутрь функции. Т.е. если на текущей линии есть какая-то функция, а не просто переменная со значением, то при клике данной кнопки, отладчик не будет заходить внутрь неё.
Step Into (F7) — делает шаг. Но в отличие от предыдущей, если есть вложенный вызов (например функция), то заходит внутрь неё.
Step Out (Shift+F8) — выполняет команды до завершения текущей функции. Удобно, если случайно вошли во вложенный вызов и нужно быстро из него выйти, не завершая при этом отладку.
Rerun (Ctrl+F5) — перезапускает отладку.
Resume Program(F9) — продолжает выполнение скрипта с текущего момента. Если больше нет других точек останова, то отладка заканчивается и скрипт продолжает работу. В ином случае работа прерывается на следующей точке останова.
Stop (Ctrl+F2) — завершает отладку.
View Breakpoints (Ctrl+Shift+F8) — просмотр всех установленных брейкпойнтов.
Mute Breakpoints — отключает брейкпойнты.
…
Итак, в текущем коде видно значение входного параметра:
$data = "23 24 11 18"
— строка с данными через пробел$nums = (4) ["23", "24", "11", "18"]
— массив, который получился из входной переменной.
Если нажмем F8 2 раза, то окажемся на строке 7; во вкладках Watches
и Variables
и в самой странице с кодом увидим, что переменная $sum
была инициализирована и её значение равно 0.
Если теперь нажмем F8, то попадем внутрь цикла foreach
и, нажимая теперь F8, пока не окончится цикл, можно будет наблюдать на каждой итерации, как значения $num
и $sum
постоянно изменяются. Тем самым мы можем проследить шаг за шагом весь процесс изменения любых переменных и значений на любом этапе, который интересует.
Дальнейшие нажатия F8 переместят линию кода на строки 11, 12 и, наконец, 15.
Дополнительно
Если нажать на View Breakpoints
в левой панели, то можно не только посмотреть все брейкпойнты, но в появившемся окне можно еще более тонко настроить условие, при котором на данной отметке надо остановиться.
В функции выше, например, нужно остановиться только когда $sum
превысит значение 20.
Это удобно, если останов нужен только при определённом значении, а не всегда (особенно в случае с циклами).
Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером
Отладка
—
Основы PHP
Один из наиболее достоверных способов убедиться, что человек разбирается в программировании — посмотреть, как он отлаживает программу, анализирует возникающие ошибки и устраняет их.
Навык отладки не появляется сам по себе, его необходимо развивать, и начинать это нужно как можно раньше. Этому способствует настройка локальной среды разработки и повторение всего, что делается в курсах у себя на компьютере. Следующие курсы как раз помогают проделать эти шаги.
Первое, что вам понадобится для отладки — хотя бы минимальное знание английского языка и умение пользоваться словарем.
В отличие от документации языка, которую можно найти на русском, сообщения об ошибках всегда отображаются на английском. Не пытайтесь отгадывать или менять код методом тыка, в надежде, что он заработает.
Прочитайте сообщение об ошибке, поймите его — это ключевое действие, на основе которого можно планировать дальнейшие шаги:
Error: Call to undefined function AppUsersundef()
/usr/src/app/src/Users.php:9
/usr/src/app/tests/UsersTest.php:27
Вывод ошибок делится на две части: непосредственно сообщение с ошибкой и бэктрейс.
Бэктрейс (он же «стектрейс») — это список всех вызовов функций от запуска программы вплоть до того места, где произошла ошибка. Это очень важный инструмент, который позволяет увидеть, как выполнялась ваша программа и какие функции вызывались.
Отладка всегда сводится к двум вещам:
- Перевести сообщение об ошибке
- Найти в бэктрейсе место в своем коде, после которого произошла ошибка
Каждая строчка в бэктрейсе представляет собой указание на файл и строчку, в которой была вызвана соответствующая функция. Бэктрейс называется back, потому что вывод строк идет в обратном порядке: наверху находится последний вызов, внизу — первый.
В рамках одного бектрейса возможны ситуации, когда часть функций вызывается где-то в сторонних библиотеках, а часть — в вашем коде.
Типы ошибок
Наиболее простые и понятные ошибки — синтаксические. Они связаны с тем, что код записан неверно: например, забыта точка с запятой в конце инструкции.
В выводе таких ошибок всегда присутствуют фразы parse error и syntax error.
Чтобы их исправить, нужно внимательно изучить то место в коде, на которое указывает ошибка:
PHP Parse error: syntax error, unexpected '}' in /usr/src/app/src/Users.php on line 7
Еще одна большая группа ошибок называется ошибками программирования. Например, к ним относятся:
- Вызов несуществующей функции
- Использование необъявленной переменной
- Передача неверных аргументов в функции, например, аргументов, имеющих неверный тип
Эти ошибки исправить труднее, чем синтаксические. Обычно они возникают в результате неправильной логики в другом, более раннем вызове.
Последний тип ошибок — логические. Исправить такие ошибки бывает крайне сложно, так как программа продолжает работать, но выдает неверный результат. Причем обычно программа выдает неверный результат не всегда, а только лишь для некоторых входных данных.
В подавляющем большинстве случаев проблема кроется в неверной логике, например, перепутана операция и вместо сложения выполняется вычитание:
<?php
// Функция должна считать сумму чисел, но считает разность:
function sum($a, $b)
{
return $a - $b;
}
Отладка
Существует множество способов отладить программу, но какой бы способ вы ни выбрали, общая идея отладки сводится к анализу того, как меняются значения переменных в процессе работы кода.
Рассмотрим конкретный пример. Ниже описана функция, которая считает сумму чисел от числа $start
до числа $finish
. Если начало равно трем, а конец — пяти, то программа должна вычислить: 3 + 4 + 5
:
<?php
function sumOfSeries($start, $finish)
{
$sum = 0;
for ($i = $start; $i < $finish; $i++) {
$sum += $i;
}
return $sum;
}
В этом коде допущена ошибка. Вы ее видите? Если очень постараться, ее можно заметить, но на это никогда не надо надеяться.
Новички часто думают, что они невнимательны и очень расстраиваются, когда допускают такие ошибки. Хотим вас успокоить: опытные разработчики допускают такие ошибки не реже новичков.
Не так важно, что вы их допускаете. Главное — чтобы вы умели отладить этот код. Этим отличаются опытные разработчики от начинающих. Никогда не пытайтесь найти ошибку с помощью медитации над кодом, сверля его взглядом. Если быстрая проверка не дала ответа, то приступайте к отладке.
Некоторые начинающие разработчики думают, что опытные программисты могут просто взглянуть на код и понять, в чем ошибка. Это совсем не так. Просто глядя на такой код, невозможно понять, а что, собственно, пошло не так, уже не говоря о нахождении самой ошибки. Нам также нужно увидеть сообщение об ошибке и начать отладку.
Глядя на код функции sumOfSeries
замечаем, что основных переменных там две: $i
и $sum
, именно они меняются в цикле. Из этого можно сделать ровно один вывод: нужно явно посмотреть, какие значения им даются на каждой итерации. После этого найти ошибку не составит труда.
Один из способов отслеживать значения переменных во время выполнения кода связан с использованием отладчиков. Отладчики интегрируются с популярными редакторами и позволяют визуально выполнить код по шагам, отслеживая любые изменения. Подробнее о том, как их использовать можно прочитать во множестве статей. Их можно найти по запросу: xdebug php <название редактора>.
В среде Хекслета отладчика нет, поэтому здесь та же задача выполняется другим способом — с помощью отладочной печати.
Суть такая же, как и в визуальном отладчике, но для вывода значения переменных используется обычная печать на экран:
<?php
function sumOfSeries($start, $finish)
{
$sum = 0;
for ($i = $start; $i < $finish; $i++) {
print_r('new iteration !!!!');
print_r($i);
$sum += $i;
print_r($sum);
}
return $sum;
}
sumOfSeries(3, 5);
// new iteration !!!!
// 3
// 3
// new iteration !!!!
// 4
// 7
То, что печатается на экран, отображается во вкладке OUTPUT
, на которую автоматически переключается редактор во время проверки. Из этого вывода сразу можно понять, что количество итераций цикла меньше, чем нужно на одну. Почему-то не выполняется сложение для последнего числа, которое обозначено как $finish
. И действительно, если посмотреть на определение, то видно, что там используется $i < $finish
вместо $i <= $finish
.
Отладочная печать через print_r
не очень удобна тем, что эта функция не ставит автоматически перенос строк. К тому же иногда хочется завершить выполнение кода сразу, как только был сделан первый вывод.
Для решения этой задачи на Хекслете подключена библиотека var-dumper. Она предоставляет две функции: dump
и dd
, которые доступны в любом месте программы. Первая просто красиво выводит переданный аргумент, а вторая — еще и останавливает выполнение кода:
<?php
$var = 'hello, world!';
dump($var);
Эта функция добавляет в вывод перевод строки, но особенно удобно использовать ее с массивами, которые мы скоро изучим.
Дополнительные материалы
- Как найти ошибки в коде?
- Psysh: REPL и интерактивный дебаггер для PHP
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты.
- PHP и MySQL
- Основы PHP
- Нарушения в работе системы PHP
Внимание! Данный курс устарел!
Переходите к новому курсу “PHP для начинающих”.
В этой статье приведены сведения о некоторых из наиболее распространенных проблем возникающих при работе с PHP, классифицированные по признакам нарушений в работе, и предложены некоторые широко применяемые способы устранения этих проблем.
Обработка и отладка ошибок
В процессе функционирования интерпретатора PHP вырабатываются ошибки нескольких типов, которые классифицируются по степени серьезности. Четыре наиболее распространенных типа ошибок описаны ниже. Дополнительные сведения по этой теме приведены по адресу www.php.net/error_reporting.
- Извещение (Notice)
-
Ошибки такого типа не слишком серьезны и не создают существенных проблем. По умолчанию эти ошибки подавляются. Их появление становится возможным только после изменения степени серьезности регистрируемых в журнале ошибок в файле php.ini.
- Устаревшие функции и конструкции (Deprecated)
-
Ошибки использования устаревших конструкций. Включаются для того, чтобы получать предупреждения о коде, который не будет работать в следующих версиях PHP.
Ошибка использования устаревших функций и конструкций - Предупреждение (Warning)
-
Ошибки такого типа возникают, если в коде, выполняемом со сбоями, возникло нарушение в работе, но выполнение программы не прекратилось. Обычно сообщение о такой ошибке отображается, но сценарий продолжает работать.
Предупреждение - Неисправимая ошибка (Fatal Error)
-
Значимое условие возникновения ошибки, в силу которого продолжение работы сценария становится невозможным. После возникновения неисправимой ошибки работа сценария прекращается.
Неисправимая ошибка
Кроме того, ошибка каждого типа представлена с помощью константы, на которую можно ссылаться в коде: E_USER_NOTICE (извещение), E_USER_WARNING (предупреждение), E_USER_DEPRECATED (устаревшие функции и конструкции) и E_USER_ERROR (неисправимая ошибка). Степень серьезности регистрируемых ошибок можно задать в сценарии вручную, с помощью функции error_reporting(), как показано в следующих примерах:
Код PHP
// Формировать сообщения только о неисправимых ошибках
error_reporting(E_USER_ERROR);
// Формировать предупреждающие сообщения и сообщения о неисправимых ошибках
error_reporting(E_USER_WARNING | E_USER_ERROR);
// Формировать все сообщения, в том числе извещения и сообщения E_STRICT
error_reporting(E_ALL);
// Не показывать никакие сообщения
error_reporting(0);
Непродуманное подавление вывода средств формирования сообщений об ошибках значительно затрудняет процесс отладки. Вместо этого чаще всего следует использовать обработчики ошибок.
Извещения никогда не передаются в клиентскую программу и не отражаются отрицательно на функциональных возможностях программы, поэтому разработчик почти всегда может без опасений отказаться от использования извещений в целях обработки ошибок. И наоборот, специализированный обработчик ошибок не позволяет обрабатывать неисправимые ошибки; в интерпретаторе PHP такие ошибки рассматриваются как достаточно серьезные для того, чтобы прекратить выполнение сценария, не задавая дополнительных вопросов. Поэтому область применения специализированных функций обработки ошибок главным образом сводится к предупреждениям. Основное назначение таких функций заключается в том, что они позволяют избежать необходимости показывать конечному пользователю сообщения об ошибках, предназначенные для программиста, и нарушать ход выполнения приложения.
Определение обработчика ошибок
На этом этапе необходимо найти ответ на следующий важный вопрос: “Какая информация должна отображаться на экране браузера пользователя при возникновении ошибки?” Обычно считается нецелесообразным и даже не рекомендуется демонстрировать перед конечным пользователем какие-либо детали, касающиеся внутреннего функционирования приложения, не говоря уже о том, что сообщения об ошибках портят внешний вид веб-страницы. Создав функцию, формирующую специализированное сообщение об ошибках, а затем установив ее в качестве применяемого по умолчанию обработчика ошибок, можно избежать такой ситуации, в которой перед глазами пользователя появляются некрасивые и непрофессионально выполненные сообщения об ошибках.
Вначале определим, какая информация должна быть предоставлена пользователю, а затем создадим функцию, как показано ниже. Эта функция должна принимать такие входные параметры, как тип ошибки, сообщение, имя файла и номер строки:
Код PHP
<?php
function error_msg($err_type, $err_msg, $err_file, $err_line)
{
static $count = 0;
$count++;
echo "<div style="width:32px; height:32px; background:url(error.png); float:left; margin:0 12px 12px 0;"></div>"
."<b>Ошибка №$count:</b><p>Извините, но на этой странице возникла ошибка. "
."Пожалуйста, отправьте следующее сообщение администратору сайта на странице <a href='help.html'>help</a>.</p>"
."<p>Тип ошибки: <em>$err_type</em>, сообщение: <em>$err_msg</em>, файл: <em>$err_file</em>, номер строки: <em>$err_line</em>"
."<hr color='red'>";
}
// Регистрируем нашу функцию в качестве обработчика ошибок
set_error_handler("error_msg");
// Генерируем ошибку, чтобы проверить вызывается ли функция error_msg
include 'undefined.php';
?>
В данном случае было решено предоставлять информацию о конкретной ошибке и о том, где она возникла. В зависимости от ситуации может оказаться оправданным решение предоставлять пользователю минимальный объем информации, поскольку ему достаточно знать, что возникла ошибка, и как ему следует действовать в дальнейшем. После того как определен специализированный обработчик ошибок, достаточно указать эту функцию обработчика в коде с помощью функции set_error_handler().
После подготовки и выполнения такого кода все ошибки, которые разрешены в соответствии с установленной степенью серьезности регистрируемых ошибок, будут обрабатываться с помощью применяемой специализированной функции, за исключением неисправимых ошибок, которые, к сожалению, также неизбежны:
Инициирование пользовательской ошибки вручную
В PHP можно инициировать пользовательскую ошибку. Такая операция приблизительно эквивалентна операции активизации исключительной ситуации в версии PHP 5 (конструкция throw). Ошибка любого типа может быть инициирована путем передачи в функцию trigger_error() сообщения об ошибке и необязательной константы с обозначением степени серьезности ошибки, как в следующем примере:
Код PHP
trigger_error("Тестируем сообщение уровня 'Notice'", E_USER_NOTICE);
Средства инициирования ошибок лучше всего использовать в сочетании со специализированным обработчиком ошибок. Сразу после инициирования такой ошибки в программе вызывается определенный в ней обработчик ошибок, который предоставляет пользователю отформатированное сообщение об ошибке. Т.е. эту функцию удобно использовать для тестирования функций обработки ошибок.
Ведение журнала и отладка
Если средства обработки исключительных ситуаций и формирования сообщений об ошибках не применяются должным образом, то задача отладки существенно усложняется. Ошибка, которую и без того трудно выявить, может стать почти неуловимой, если программист непродуманно использует способы подавления или перенаправления сообщений об ошибках. Но достаточно лишь немного более тщательно продумать применение обработчиков ошибок, и сопровождение приложения существенно упрощается.
В приведенных выше примерах процесс обработки ошибок в основном рассматривался как средство создания интерфейса, в котором пользователь не обнаруживает следов возникших нарушений в работе. По такому же принципу можно обеспечить применение этих средств для упрощения регистрации ошибок и отладки в интересах программиста. Для этого достаточно включить вызов встроенной функции, такой как error_log(), и передать в эту функцию любую релевантную информацию, которая может помочь в процессе отладки, как в следующем коде. Следует учитывать, что в ходе разработки может потребоваться прибегнуть к использованию функции getTraceAsString(), позволяющей обеспечить ведение журналов:
Код PHP
function error_msg($type, $msg, $file, $line)
{
// Записать в журнал ошибок
$log_msg = "Тип ошибки: $type, сообщение: $msg, файл: $file, номер строки: $line, время возникновения: ".time();
$log_path = "tmp/php_errors.log";
error_log($log_msg, 3, $log_path);
}
set_error_handler("error_msg");
trigger_error("Тестируем сообщение уровня 'Notice'", E_USER_NOTICE);
Функция error_log() принимает в качестве второго параметра одно из четырех целых чисел, описание которых приведено ниже. Этот параметр задает тип сообщения в сочетании с третьим параметром, который указывает на местонахождение объекта — получателя сообщения об ошибке:
-
0 — сообщение, регистрируемое с использованием общесистемного механизма ведения журналов операционной системы.
-
1 — сообщение об ошибке, передаваемое по указанному адресу электронной почты (в качестве четвертого параметра можно ввести дополнительные заголовки).
-
2 — сообщение об ошибке, передаваемое через отладочное соединение PHP (должна быть разрешена дистанционная отладка).
-
3 — сообщение об ошибке, добавляемое в конец указанного файла журнала ошибок.
Ошибки, обнаруживаемые интерпретатором PHP
После того, как мы рассмотрели виды ошибок и способы их обработки, давайте рассмотрим наиболее распространенные нарушения при работе с PHP.
Проблемы, связанные с инсталляцией PHP
Я не стану читать мораль на тему, что не следует одним махом проходить все этапы инсталляции, не разобравшись в документации, а приведу описание нескольких часто встречающихся признаков нарушения в работе, которые обычно появляются после того, как инсталляция PHP выполняется впервые. Если вы устанавливали PHP не вручную, а например через WAMP-сервер, то приведенные ниже проблемы скорее всего у вас не возникнут.
Признак нарушения в работе: в окне браузера отображается текст файла
Если в окне браузера появляется текст сценария PHP вместо результирующего кода HTML, такая ситуация явно свидетельствует о том, что не происходит вызов машины PHP. Проверьте, что обращаетесь к сайту с помощью веб-сервера, а не файловой системы. Применяйте следующий вариант:
https://localhostpre>а не следующий, например:
file://home/httpd/htmlpre>Признак нарушения в работе - блоки PHP отображаются при их передаче по протоколу HTTP в виде текста или браузер выводит приглашение, согласно которому вам следует сохранить файл
Вызов машины PHP не происходит должным образом. Если запрос на получение файла передан правильно, по протоколу HTTP, как было указано в предыдущем подразделе, то наиболее распространенной причиной этой ошибки является то, что заданы не все расширения имен файлов, которые должны обслуживаться веб-сервером и распознаваться интерпретатором PHP. Вторая по степени распространенности причина состоит в том, что файл php.ini находится не в должном месте или содержит неправильную директиву настройки конфигурации.
Признак нарушения в работе - не найден сервер или хост либо страница не могут быть отображены
Если браузер не может найти используемый сервер, то, по-видимому, имеет место нарушение конфигурации DNS (Domain Name Service — служба доменных имен) или веб-сервера. Если доступ к сайту может быть получен с помощью IP-адреса (например, https://127.0.0.1p>
Если невозможно получить доступ к сайту с помощью IP-адреса после выполнения новой инсталляции, то, по всей видимости, пользователь не смог успешно выполнить привязку IP-адреса к сетевому интерфейсу или настроить конфигурацию домена httpd для обработки запросов, относящихся к конкретному домену. А если доступ к сайту не может быть получен с помощью IP-адреса, притом что применяемая инсталляция уже успешно работала, то наиболее вероятное объяснение состоит в том, что веб-сервер остановлен или недоступен по причине, не относящейся к PHP.
Проблемы формирования страницы
В данном разделе рассматриваются проблемы, при возникновении которых интерпретатор PHP, собственно говоря, не сообщает о каких-либо ошибках, но пользователь обнаруживает в окне браузера не те результаты, на получение которых он рассчитывал.
Признак нарушения в работе - полностью пустая страница
Появление пустой страницы может быть вызвано самыми разнообразными причинами. Одной из наиболее распространенных становится неисправимая ошибка в коде PHP, после обнаружения которой интерпретатор PHP не может возобновить нормальную работу. Начинайте отладку с верхней части файла PHP, который вы пытаетесь открыть в браузере, поместив вызов функции die() после открывающего дескриптора <?php:
Код PHP<?php die(print "hello"); ...
Если после обновления страницы вы увидите в браузере слово hello, это означает, что проблемы с веб-сервером и самим модулем PHP исключены. Продолжайте перемещать оператор вызова функции die() в коде PHP дальше, до тех пор, пока снова не появится ошибка, выражающаяся в появлении пустой страницы. Не забывайте, что неудачное завершение сценария может также происходить в результате обработки любых файлов, включенных с помощью require, require_once, include и тому подобных конструкций. Если после ввода оператора вызова функции die() непосредственно перед включенным файлом сценарий работает, а вслед за перемещением оператора вызова функции die() непосредственно после включенного файла перестает работать, то можно сделать вывод, что нарушение в работе возникает из-за включенного файла.
Безусловно, еще одной из возможных причин такой ситуации может явиться также то, что модуль PHP вообще не работает. Проверьте это предположение, просмотрев другую страницу из того же каталога, в отношении которой вы уже убедились, что она правильно обрабатывается интерпретатором PHP.
Наконец, пустое окно браузера обнаруживается в тех ситуациях, когда интерпретатор PHP сталкивается с достаточно серьезной ошибкой, а средства формирования сообщений об ошибках отключены. По-видимому, средства вывода сообщений об ошибках следует отключать на производственных серверах по соображениям безопасности, но на серверах, применяемых для разработки, средства вывода сообщений об ошибках в браузер оказывают огромную помощь. Проверьте в файле php.ini параметр display_errors и убедитесь в том, что все необходимые параметры заданы правильно. Если же пользователь действительно отвергает возможность вывода сообщений об ошибках в окно браузера, то ему придется широко использовать в составе средств обработки исключении функцию error_log() как показано выше.
Признак нарушения в работе - в окне веб-браузера обнаруживается код PHP
Если в окне браузера обнаруживается в буквальном виде код PHP, а не развертывается код HTML, который должен быть сформирован в этом фрагменте PHP, то, по-видимому, где-то пропущен начальный дескриптор PHP. (При этом предполагается, что интерпретатор PHP функционирует успешно, а в используемой инсталляции предусмотрены правильные форматы дескрипторов PHP.)
Можно легко забыть, что интерпретатор PHP рассматривает включаемые файлы как представленные в коде HTML, а не в коде PHP, если пользователь не укажет интерпретатору иное с помощью открывающего дескриптора в начале файла.
Ошибки при загрузке страницы
Если интерпретатору PHP не удается найти файл, запрос о загрузке которого получен от пользователя, то обнаруживается целый ряд разнообразных ошибок, описанных ниже.
Признак нарушения в работе — страница не может быть найдена
Если появляется сообщение о том, что страница не может быть найдена, притом, что другие файлы PHP загружаются без каких-либо нарушений, то, по-видимому, допущена ошибка при написании имени файла или определении пути доступа. Еще один вариант состоит в том, что могла возникнуть путаница в отношении того, где находится корневой каталог документов веб-сервера.
Признак нарушения в работе - сообщение Failed opening [file] for inclusion (He удалось открыть [файл] для включения)
Если в файле PHP предусмотрено включение других файлов PHP, иногда встречаются ошибки, подобные показанной ниже:
Warning Failed opening 'C:InetPubwwwrootasdf.php' for inclusion (ihclude_path='') in [no active file] on line 0Можно считать, что это сообщение представляет собой вариант сообщения Page cannot be found (He удается найти страницу), относящийся к включаемым файлам. Появление этого сообщения свидетельствует о том, что интерпретатору PHP не удалось загрузить даже первую строку активизированного файла. Активизированный файл отсутствует, поскольку не удается найти файл с указанным именем.
Появление такого сообщения возможно также в связи с тем, что права доступа к файлу, который вы пытаетесь загрузить, заданы неправильно.
Ошибки интерпретации
Наиболее распространенная категория ошибок возникает при обработке содержащего орфографические ошибки или синтаксически неправильного кода PHP, который вызывает сбои в работе машины интерпретации PHP.
Признак нарушения в работе — сообщение об ошибке интерпретации (Parse error)
Безусловно, количество причин возникновения проблем при интерпретации велико, но признак этого нарушения в работе почти всегда остается одинаковым — сообщение об ошибке интерпретации, Parse error:
Сообщение об ошибке интерпретации (Parse error) Все наиболее распространенные причины ошибок интерпретации, подробно описанные ниже, являются довольно незначительными и допускают несложное исправление, особенно если учесть, что интерпретатор PHP сам подсказывает способ их исправления. Тем не менее при любой ошибке интерпретации возвращается идентичное сообщение (в котором изменяются только имена файлов и номера строк) независимо от причины. Любой код HTML, который может находиться в файле с ошибками, не отобразится или не обнаружится в исходном коде, даже если этот код находится перед фрагментом PHP, вызвавшем появление ошибки.
Отсутствие точки с запятой
Ошибка интерпретации возникает, если точка с запятой не стоит, как положено, после каждого оператора PHP. В следующем примере фрагмента PHP в первой строке отсутствует точка с запятой, поэтому операция присваивания значения переменной так и не выполняется:
Код PHP
$count = 2 $level = 4
Отсутствие знаков доллара
Еще одна весьма распространенная проблема состоит в том, что пропущен знак доллара, предшествующий имени переменной. Если знак доллара отсутствует в операторе присваивания переменной начального значения, как в следующем примере:
Код PHP
count = 2;
то возникает сообщение об ошибке интерпретации. Но если вместо этого знак доллара отсутствует в применяемом впоследствии операторе вывода значения переменной, как в следующем примере:
Код PHP
$count = 2; echo "Количество: count";
то интерпретатор PHP не выводит сообщение об ошибке интерпретации. Вместо этого в окне отображается строка "Количество: count".
Это — превосходный пример, показывающий, почему не следует рассчитывать на то, что интерпретатор PHP сообщит вам обо всех ошибках на странице. Безусловно, сообщения об ошибках PHP являются более информативными по сравнению с большинством других средств динамического формирования информационного наполнения, но ошибки, подобные указанной, вполне могут остаться незамеченными, если усилия, предпринятые при проверке правильности кода, не будут соответствовать требованиям решаемой задачи.
Если вам приходится затрачивать значительную часть времени на отладку кода PHP, то для вас может оказаться буквально бесценным редактор текста, позволяющий переходить к строкам с указанными номерами и подсвечивающий все синтаксические ошибки. Я, например, использую удобную IDE Adobe Dreamweaver, которая динамически подсвечивает синтаксические ошибки, а также содержит нумерацию строк, чтобы можно было легко найти другие виды ошибок, которые отображаются в окне браузера:
Подсветка ошибки в Adobe Dreamweaver Подобные программы позволяют избежать большого количества синтаксических ошибок на этапе написания кода.
Проблемы, связанные со сменой режима
Еще одна разновидность нарушений в работе возникает в связи с неправильным переходом в режим PHP и из режима PHP. Если блок PHP не закрыт должным образом, как показано ниже, то возникает ошибка интерпретации:
Код PHP
<?php $count = 2 $level = 4; </body> </html>
Данная конкретная проблема переключения режима очень часто возникает при использовании коротких блоков PHP. И наоборот, если пользователь не обозначит должным образом начало блока PHP, то весь оставшийся блок, предназначенный для обработки, будет выглядеть как код HTML.
Кавычки, не обозначенные управляющими последовательностями
При использовании такого стиля разработки, в котором для выработки кода HTML в максимальной степени применяется код PHP, часто возникает еще одна ошибка интерпретации, связанная с тем, что кавычки в строках не обозначаются управляющими последовательностями:
Код PHP
// Неправильная строка echo "Он сказал, - "Что нам делать?""; // Правильная строка echo "Он сказал, - "Что нам делать?"";
Другие причины ошибок интерпретации
Проблемы, названные выше, не составляют исчерпывающий список источников ошибок интерпретации. Дело в том, что сбой в работе интерпретатора возникает под воздействием любых нарушений формата оператора PHP, включая незакрытые круглые и квадратные скобки, операции без операндов, не заключенные в круглые скобки выражения проверки в управляющих структурах и т.д. Иногда сообщение об ошибке интерпретации включает сведения о том, что ожидал встретить в коде интерпретатор PHP, но так и не смог обнаружить; такие сведения могут оказаться полезной подсказкой. Если номер строки, указанный в сообщении об ошибке интерпретации, относится к самой последней строке файла, это обычно означает, что какая-то программная конструкция, заключенная в парные символы (кавычки, круглые, фигурные скобки и т.д.), была открыта, но так и не закрыта, а интерпретатор PHP продолжал искать закрывающий символ до достижения самого конца файла.
Проблемы, связанные с использованием функций
Многие проблемы, касающиеся вызова функций, приводят к возникновению неисправимых ошибок, а это означает, что интерпретатор PHP отказывается от обработки оставшейся части сценария.
Признак нарушения в работе - сообщение Call to undefined function my_function()
В коде PHP предпринимается попытка вызвать функцию my_function(), которая еще не была определена. Такая ситуация может возникнуть просто в связи с тем, что допущена ошибка при написании имени функции (встроенной или определяемой пользователем), или лишь потому, что не дано определение функции. Если для загрузки определений пользовательских функций из файлов используется конструкция include или require, следует убедиться в том, что загружаются именно те файлы, которые требуются.
Если же рассматриваемая проблема касается весьма специализированной, встроенной функции (например, относится к средствам XML или к средствам математических вычислений произвольной точности), то причина может состоять в том, что при компиляции и сборке исполняемого файла интерпретатора PHP не было разрешено применение соответствующего семейства функций.
Признак нарушения в работе - сообщение call to undefined function ()
В данном случае интерпретатор PHP пытается вызвать некоторую функцию, но не имеет даже возможности определить ее имя. Такая ситуация возникает исключительно в тех случаях, если в коде применяется выражение в форме $my_function(), где само имя функции показано как переменная. Это означает, что разработчик, скорее всего, случайно поместил знак $ перед выражением вызова функции my_function(), имеющим смысл, или ошибся, специально используя средство задания имени функции с помощью переменной языка PHP. А поскольку $my_function представляет собой переменную с незаданным значением, то интерпретатор PHP подставляет в качестве значения этой переменной пустую строку (которая не может служить в качестве имени определенной функции), после чего выдает приведенное в названии этого подраздела маловыразительное сообщение об ошибке.
Признак нарушения в работе - сообщение Cannot redeclare my_function()
Причина этой проблемы проста — где-то в используемом коде имеется повторно заданное определение функции my_function(), а такая ситуация в языке PHP является недопустимой. Убедитесь в том, что в коде не применяется конструкция include для включения одного и того же файла с определениями функций больше одного раза. Чтобы предотвратить возникновение такой ошибки, необходимо использовать конструкцию include_once или require_once, но с учетом того предостережения, что ошибка, связанная с повторным включением, при этом не устраняется, а просто перестает обнаруживаться.
Почему указанную ситуацию следует рассматривать как потенциальную причину нарушений в работе? Дело в том, что вполне можно представить себе такую ситуацию, что разработчик определил две полностью разные функции, но непреднамеренно присвоил этим функциям одинаковые имена. Это связано с тем риском, что допущенная при этом ошибка проявится в самый неожиданный момент.
Признак нарушения в работе - сообщение Wrong parameter count
Функция, имя которой указано в сообщении об ошибке Wrong parameter count, вызвана с меньшим или большим количеством фактических параметров по сравнению с тем, на обработку которого она рассчитана. Если задано больше параметров, чем требуется, то никаких затруднений не возникает, но если используется меньше параметров по сравнению с ожидаемым, то возникает ошибка.
Обработка исключений
Отладка программ
Оценить статью:
Меня запарили спрашивать всякую фигню. Поэтому сейчас расскажу пару способов быстро найти ошибку в коде.
1. Ошибка синтаксиса.
В этом вам поможет любой нормальный редактор с проверкой синтаксиса. Я использую Eclipse SDK с установленным плагином PDT. Замечательно подсвечивает синтаксис PHP, а также HTML, XML и XSL. Слегка работает с JS. Автоподстановка и прочие прелести в комплекте. Требует JRE для работы. Кушает много памяти.
Также ошибки синтаксисы выражаются во всяких загадочных фразах:
unexpected ЧТО-ТО, expecting ЧТО-ТО_ДРУГОЕ or ЕЩЁ_ЧЕГО-НИБУДЬ on line N — намекает нам о том, что там требуется ЧТО-ТО_ДРУГОЕ вместо ЧТО-ТО. Обычно это строка N-1. Например, скобку забыли поставить или точку с запятой.
unexpected $end — скорее всего забыли поставить закрывающую фигурную скобку.
Вообще слово unexpected переводится как неожиданный. Поэтому если вы это видите — знайте, что-то не там поставили или не дописали. Это как вам должны были выдать зарплату, а выдали мешок яблок. Вот это будет unexpected ‘мешок яблок’ 🙂
Call to undefined function — вы пытаетесь вызвать что-то несуществующее. Может написали prinf(); вместо printf(); ну и всё такое прочее.
Если вдруг у вас ничего не работает, но ничего не выводится, то поставьте параметр error_reporing = E_ALL; Будет отображать все ошибки, включая notice’ы.
Если даже с включенными ошибками у вас ничего не работает вообще — то тут уже надо курить логи апачи и php.
2. Ошибки логики.
Опять-таки надо первым делом включить error_reporting в E_ALL. Иначе уведомления типа: undefined index, undefined variable показываться не будут, и вы долго будете думать, «что ж таки случилось?».
Далее. Если у вас на выходе получается не то, что вы хотите — делайте вывод своей переменной на каждом шаге. Причём не просто через print/echo, а через var_dump(), который покажет вам и тип переменной и всю её начинку.
Я вообще пользуюсь своей версией var_dump() ‘a:
-
/**
-
* Выводит информацию о переменной
-
* @param $text переменная для вывода
-
* @param $exit прекращать работу после вывода
-
*/
-
function vardump($text, $exit = false) {
-
print ‘<pre>’;
-
var_dump($text);
-
print ‘</pre>’;
-
if($exit)
-
die();
-
}
Прелесть этой функции в том, что если у вас где-то есть header(‘Location:’); то вызвав vardump($a,1); вы завершите скрипт и получите информацию о своей переменной.
А вообще, для самой классной отладки — надо ставить xDebug.
От автора: я опять сегодня не выспался! Вчера отлавливал ошибки в написанном скрипте, а сегодня комар жужжал под ухом всю ночь. И кажется, что это насекомое сродни тому багу, который я прошлой ночью еле нашел. В общем, сегодня (раз уж мне не спится) узнаем о кодах ошибок в PHP.
Если их не видно
Причин, почему ошибки не выводятся на экране, может быть несколько:
Их вывод отключен хостером специально – таким образом он заботится о повышении безопасности своего серверного пространства. В том числе и вашего ресурса. И все потому, что в описаниях некоторых ошибок отладчик выводит конфиденциальную информацию. Умелый хакер сможет легко использовать ее для взлома вашего сайта. Например, при указании неправильного пароля при подключении к базе, расположенной на сервере MySQL. В результате на экран выводится описание ошибки, содержащее логин активного пользователя СУБД.
В файле .htaccess.
В настройках ядра языка.
Все эти «частные» случаи мы рассматривали в одном из наших предыдущих материалов. Но так как нами используется Денвер, то я кратко опишу решение данной проблемы в нем.
Перед тем, как найти ошибку коде PHP, сначала нужно ее вывести на экран. Если это не происходит, тогда прямая дорога в php.ini.Здесь нужно активировать значения нескольких параметров:
display_errors.
error_reporting.
display_startup_errors.
Данные настройки расположены в разделе «Error handling and logging».
Логов нет!
Как отмечалось ранее, в большинстве случает на хостингах вывод программных багов на веб-страницах отключен. Но это не значит, что они недоступны для отслеживания и отладки владельцам ресурсов. Все данные об ошибках записываются в файлы логов.
В Денвере данная функция (по умолчанию) отключена. Это можно легко исправить, прописав нужный код в конфигурационном файле (в том же разделе).
Снова откройте php.ini и внесите в него выделенные ниже строки. Точнее, одна из них уже должна быть, но лучше проверить. С помощью этих директив (log_errors и error_log) разрешается запись сообщений обо всех ошибках. А также задается путь к файлу логов, с помощью которого вы сможете осуществить PHP проверку кода на ошибки.
После редактирования конфигурационного файла перезапустите локальный сервер, чтобы все изменения вступили в силу.
Проверяем
Теперь проверим, что у нас вышло. Для этого запустим умышленную синтаксическую неточность в коде: неправильно объявим переменную PHP.
Теперь заглянем в созданный файл логов.
Как видим, в него записалась вся информация о допущенном баге. Здесь же мы натыкаемся на «упоминание» об одном из основных типов ошибок – parse error. Это говорит о том, что мы нарушили синтаксическое правило языка (объявление переменных).
Как можно еще проверить PHP код на ошибки? Применить функцию set_error_handler(), которая позволяет задать пользовательский обработчик. Но ее использование при включенном родном handler не имеет смысла. Кроме этого пользователь может перехватывать не все типы ошибок. Например, фатальные error вам (как и мне) переопределить не удастся. Пример:
<?php error_reporting(0); function user_handler($n, $str,$file, $line) { echo “Номер: “.$n.“<br />”. “Описание: “.$str.” <br />”. “Имя файла: “.$file.“<br />”. “Строка кода: “.$line; return true; } set_error_handler(‘user_handler’, E_ALL); require(“nofile.php”); ?> |
Сначала мы отключили нативный обработчик (error_reporting(0)). Затем создали собственную функцию и передали ее в качестве аргумента set_error_handler(). После чего инициировали ошибку, подключив несуществующий «в природе» файл.
Онлайн
Осуществить проверку кода PHP на ошибки также можно с помощью специализированных сервисов. Вот несколько из них: codepad, PHP Assist
А возле меня почему-то комаров стало больше! Или это звездочки летают? Пойду, наверное, посплю, пока ко мне дичь посерьезней (белочка) не прискакала :). Спокойной ночи!