Меню

Php как найти ошибку в коде

Как найти ошибку в своем коде?

Быстрые рекомендации.
1. Убедитесь, что вы видите сообщения об ошибках, если они возникают.
Для этого надо добавить в начало скрипта 2 строчки
ini_set(‘display_errors’,1);
error_reporting(E_ALL);
Хотя в некоторых случаях это всё равно не поможет. Тогда смотрите ошибки в логах веб-сервера.
Ещё можно добавить в файл .htaccess строчку
php_flag display_errors 1
Обязательно убрать всех собак (@) из кода!
Если апач выдаёт ошибку 500 — значит надо смотреть текст ошибки в логе ошибок веб-сервера.

2. При работе с БД надо её настраивать так, чтобы она сообщала об ошибках.

Для mysqli, перед коннектом всегда должна быть строчка

Если используется PDO, то соединяться, как написано здесь: http://phpfaq.ru/pdo

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

4. При проблемах в аплоаде в первую очередь смотрите массив $_FILES ( print_r($_FILES); ). Описания ошибок из $_FILES[‘filename’][‘error’] есть в мануале.

5. При проблемах во взаимодействии сервера и клиента (куки, сессии, запросы)- в обязательном порядке смотреть обмен HTTP заголовками

6. Закомментируйте строчку с header(«Location:»), если ищете обшибку в обработчике POST запроса

7. При отладке AJAX запросов смотрите ответ сервера в FireBug-e и его аналогах (кнопка F12 в любом браузере), вкладка Network — Preview.

8. И САМОЕ ВАЖНОЕ: запуская скрипт, смотрите не то, что показывает браузер, а ИСХОДНЫЙ HTML код!.

Получив сообщение об ошибке, вы можете его прочитать и исправить.
Если не справились — пишите на форум. При этом КОПИРУЙТЕ сообщение об ошибке, и КОПИРУЙТЕ небольшой — 3-5 строк — кусок кода, на который указывает ошибка. Повторяю — КОПИРУЙТЕ! никакой отсебятины!

Если вы всё равно не нашли ошибку — читайте дальше:

Введение. Очень важное.
Ты написал программу, а она не работает.
Вариантов ты видишь немного — либо сидеть и пытаться умственным усилием обнаружить ошибку, в сотый раз просматривая код, либо пойти на форум и попросить, чтобы там тебе нашли ошибку.
Самое интересное, что есть третий, в сто раз лучше первых двух.
Этот способ называется «Отладка программы». По-английски — debug.
Заключается он в том, чтобы заставить программу саму показать, где в ней ошибка.
Это мало того, что получится быстрее, чем спрашивать на стороне — так зачастую это единственный способ решить проблему. Единственный.
Я тебе сейчас открою страшный секрет. В мире НЕТ программистов, которые пишут код, как художники на Арбате — сел, наваял, отдал. Нету. И не будет.
Процесс написания программы — циклический: Написал кусок кода — посмотрел, как работает. Если не работает — ищем ошибки. Работает — пишем дальше.
Только так. Других вариантов нет.
Больше того. В большинстве случаев совершенно бесполезно вываливать на форум свой код, и спрашивать — «В чём ошибка?». На форуме не сидят волшебники вперемешку с телепатами. И гадалок с прорицателями — тоже нет. Поэтому отгадывать, в чём, теоретически, может быть ошибка, никто не будет. Ошибку найти может только хозяин программы. На своём сервере. Со своими настройками и опечатками. Поэтому локализовать ошибку — найти место, где она происходит, определить тип ошибки — можно только самостоятельно. А вот исправить её на форуме помогут. Если не получится самому.

Те, кто приходит к веб-программированию от дизайна, или от игр, или от нечего делать, просто не знают этой страшной тайны: Основное время программиста уходит не на написание кода. Основное время программиста уходит на поиск ошибок и отладку. Это не шутка. Это правда. И если вы решили заняться программированием, то вам придётся искать ошибки точно так же, как это делают все остальные.
К сожалению, очень много людей приходит к PHP вообще без опыта программирования и, как следствие — никогда не слышали об отладке.
А это и есть самое главное в программировании — умение искать ошибки.
И мы с тобой сейчас будем учиться их искать.

Программа не работает. Что можно сделать в этом случае?

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

Пояснение: Очень многие люди не понимают, что такое сообщение об ошибке. В основном эти люди делятся на две категории. Первая считает, что сообщения об ошибках — это блажь разработчиков языка, надоедливый сервис, сделанный для того, чтобы программисту было не скучно. И избавляться от сообщений надо любыми доступными способами. Вторая категория не выросла из школьного возраста и воспринимает не смысл ошибки, а лишь сам факт. Принимают пхп за стервозного завуча, который ругает не по делу, а абстрактно, за то, что оболтус. То есть, факт появления ошибки вызывает у этих людей только негативные эмоции, а в смысл они даже не пытаются вчитываться.

Это чудовищные заблуждения. Сообщения об ошибках — это ПОМОЩЬ! Это громадная помощь программисту. Как ей воспользоваться, мы рассмотрим ниже.

Даже самый рабочий код, которому ты на 100% доверяешь, и который на соседней машине работает, как часы, может выдавать сообщение об ошибке. Причин тому может быть бесконечное множество. Это и такой распространенный случай, как отсутствие прав доступа к файлам, и такие экзотические, как запрещение провайдером выполнения самых распространенных и безобидных функций.

Твоя задача — обеспечить интерпретатору возможность сообщить тебе об ошибке при возникновении оной.
Ты должен быть уверен, что если выполнение программы вызывает ошибку, то ты эту ошибку увидишь.
Что интерпретатору не запрещено сообщать тебе об ошибке.
Что ты запросил все варианты вывода сообщения об ошибке.

Во-первых, надо выяснить, выводятся ошибки на экран или пишутся в лог. Обычно, домашний, или тестовый сервер настраивается так, чтобы ошибки выводились на экран. Рабочий же сервер, с сайтом в публичном доступе ОБЯЗАТЕЛЬНО должен быть настроен так, чтобы ошибки не выводились на экран (поскольку посетителю они все равно ничего не скажут, а программист их не увидит), а писались в лог, где программист их увидит.
Если ты не уверен, и не знаешь, где посмотреть, а ошибку найти надо срочно, то напиши в самом начале скрипта две строчки
ini_set(‘display_errors’,1);
error_reporting(E_ALL ^E_NOTICE);
Эти две строки заставят выводить сообщения обо всех критических ошибках на экран.
Если никаких ошибок не выведется, надо написать
error_reporting(E_ALL);
Это очень сильно поможет, показав несуществующие переменные и другие мелкие ошибки, которые обычно игнорируются, но от которых может зависеть работоспособность программы.
ВАЖНО! В случае ошибки синтаксиса, по очевидным причинам, установка с помощью ini_set не сработает.
Поэтому лучше на неё не надеяться, а либо исправить в php.ini (или в .haccess добавить строчку php_flag display_errors 1 ), либо искать ошибку в логе.

Во-вторых, убедись, что в коде отсутствуют символы ‘@’ перед именами функций. Этот запрещает вывод сообщения об ошибке. Хорошенькое дело! Ты ошибку ищешь-ищещь, а сам же своей программе рот заткнул.

Если ты уверен, что ошибка есть, но на экран она всё равно не выводится — найди лог ошибок веб-сервера. Обычно, это файл с названием error_log. Где он находится — надо посмотреть в документации или спросить в службе поддержки провайдера.

При возникновении проблем с функциями mysql (supplied argument is not a valid MySQL result resource) под строкой, где произошла ошибка, обязательно надо вывести на экран mysql_error() и сам запрос — для визуального контроля и копирования на форум.

При работе с изображениями, чтобы увидеть сообщение об ошибке, обязательно надо догадаться отключить вывод заголовка, говорящего браузеру, что дальше идет картинка.
При аплоаде в первую очередь смотрите массив $_FILES.
При проблемах во взаимодействии сервера и клиента — в обязательном порядке смотреть обмен HTTP заголовками
И всегда смотрите не то, что показывает браузер, а ИСХОДНЫЙ HTML код!

Допустим, сообщение об ошибке появляется, и ты его получил. Что делать дальше? Очень просто — прочесть и исправить. Если не хватает знания английского языка, то стоит либо воспользоваться переводчиком, либо взять значащую часть этого сообщения и запросить Google. 90% вероятности, что кто-то с такой ошибкой уже сталкивался, и ты тут же прочтешь ответ.
Если же не нашел, то задай вопрос в форуме, точно скопировав небольшой (3-5 строк) кусок кода, в котором произошла ошибка, точно указав строку, о которой говорится в сообщении об ошибке, а так же — самое главное! — само сообщение об ошибке.
Согласись, что с такой информацией тебе на форуме помогут гораздо скорее и качественней?

Отладка и поиск ошибок в своем алгоритме.
Но бывает так, что программа не вызывает ошибок, но все равно не работает, или работает не так, как надо.
Тут уже виноват или алгоритм или какие-то внешние факторы.
Однако и тут можно найти место, где происходит ошибка.
Но только при одном условии.
что ты четко представляешь, что делает твоя программа, каждая функция, каждая строка в ней. Потому, что если ты представляешь, то можешь предсказать, какие значения должны иметь переменные на каждом этапе выполнения.
А дальше все ОЧЕНЬ просто!
Во-первых, надо разделить программу на логические блоки.
Допустим, скрипт выводит форму, получает ее, и записывает данные в базу. ТРИ шага! И в любом из них может быть ошибка, приводящая к тому, что данные в базу не записываются.
Надо проконтролировать на каждом из участков — все ли переменные имеют то значение, которое ожидается.
Программа ведь работает с переменными.
Как проверить?
Выводить все используемые переменные на экран! И визуально контролировать их содержимое.
Всего-то лишь написать проблемных местах var_dump($var) и выяснится, что переменная-то пустая!
И уже можешь пойти на форум не с вопросом «у меня вот код на 100 строк, где ошибка?», а «я написал функцию, но почему-то, когда обращаюсь в ней к переменным, они все пустые». или «из формы не передаются переменные».
Между этими двумя способами задания вопросов — пропасть.
Первый не может тебе помочь никак. Ты, собственно, и сам не знаешь, что у тебя за проблема. А при втором ты уже знаешь проблему, и, если сам не справился с ее решением, то можешь задать на форуме конкретный вопрос.

Еще очень поможет избежать ошибок в программе выставление error_reporting в E_ALL с самого начала работы скрипта.
Если при отлове критических ошибок сообщения о потенциальных ошибках могут нам помешать увидеть главную, то при разработке нам желательно видеть все — и потенциальные в том числе. Скажем, при E_ALL, при обращении к несуществующей переменной, PHP выдаст предупреждение. То есть, тебе не придется самому выводить переменную, чтобы выяснить, что ты не присвоил ей никакого значения — РНР тебя сам предупредит.

Пример отладки.
Из html формы передаются чекбоксы с именами c_1, c_1, c_3. c_10
В скрипте мы пытаемся в цикле вывести
for ($i=1, $i
скрипт ничего не выводит.
Начинаем отлаживать.
Сначала смотрим в исходный код html страницы. соответствует ли она стандартам?
Допустим, соответствует. Значит, проблема не в форме.
Далее, проверяем в скрипте — а есть ли такая переменная, к которой мы обращаемся — массив $_POST?
пишем

echo ‘

‘;
var_dump($_POST);

Убеждаемся в том, что массив есть и все элементы на месте. Значит, проблема не в передаче.
Значит, мы как-то неправильно обращаемся к массиву.
обращаемся мы к нему так: $_POST[‘с_$i’]
Надо проверить — а во что превращается ‘с_$i’?
делаем echo ‘с_$i’; и видим. совсем не то, что ожидали увидеть.
И вот теперь уже идем либо читать документацию про строки в пхп (что предпочтительнее), либо — на форум, с вопросом «почему у меня переменная не заместилась своим значением». Каковой вопрос будет гораздо лучше звучать, чем «у меня форма не работает».
Понятно?

Следует понимать, что здесь приведён пример, Нереальный. Показан алгоритм действий.
В реальности, при error_reporting(E_ALL); PHP сразу же показал бы, что индекс массива у вас неправильный.

Самое важное — знать, что ты хочешь получить.
Примерно половина вопросов на форумах вызвана тем, что человек делает что-то. НЕ ЗНАЯ, что именно!
Самый гениальный вопрос всех времён и народов: «у меня база съела все переводы строк из текстарии».
Человек просто не дал себе труд посмотреть, как будет выглядеть HTML, который он хочет получить, и решил, что переводы строк съела база.
И так во всём.
Непризнанный гений строит сложный SQL запрос, а когда его спрашивают, как запрос должен выглядеть — он только хлопает глазами. ВСЕГДА СНАЧАЛА составьте запрос руками и выполните в консоли или phpmyadmin! А после того, как получили нужный запрос и отладили — милости просим, составляйте его на пхп.
Работа с удалённым хостом через сокет по протоколу HTTP — то же самое! Сначала научитесь выполнять все команды руками, посмотрите ответы сервера глазами, а потом моделируйте этот диалог в пхп.
Работа с яваскриптом по тому же методу описана в факе «на танке»

Запомните — на пхп вы работаете только со СТРОКАМИ! HTML страница, которую вы создаёте скриптом — это для пхп всего лишь набор строк! Ему без разницы, что в этом наборе — теги img, script или frame. Пхп за вас не сделает переводы строк, не нарисует яваскрипт. Если вы не знаете яваскрипта — то не пытайтесь создавать программу на нём с помощью PHP.
Открывая соединение с удалённым хостом, вы посылаете строку в сокет, вы получаете строку из сокета. Пхп ничего не понимает в этих строках и за вас диалог вести не будет! Это ВЫ должны чётко понимать, что вы хотите послать в сокет, и что получить! Поэтому возьмите программу telnet, соединитесь с нужным хостом и пробуйте сначала САМИ сделать то, что хотите заставить сделать пхп.
Если у вас не работает скрипт с сокетами — бегом в телнет смотреть, что происходит!
SQL запрос — это СТРОКА. Вы должны себе чётко представлять, какой запрос получится в результате вашего хитроумного пхп-кода! Сервер БД не понимает конструкций intval, date, mktime и так далее! Это всё пхп-код. Результатом которого будет являться строка корректного SQL запроса. прежде, чем писать пхп код, вы должны ЧЁТКО СЕБЕ ПРЕДСТАВЛЯТЬ, КАК ДОЛЖЕН ВЫГЛЯДЕТЬ SQL ЗАПРОС В РЕЗУЛЬТАТЕ!
Если у вас не выполняется SQL запрос 0 выводите его на экран и смотрите — что нагородили своим скриптом!

Заключение.
Отладка — главное занятие программиста.
Отладка — единственный и самый мощный способ найти ошибку в программе.
Отладка состоит из двух основных компонентов:
1. Максимально упрощать пример. Если у вас не работает программа, которая рисует форму,получает данные, записывает данные формы в базу и выводит их снова, то разбейте программу на составляющие и выполняйте по очереди.
Если у вас не работает сложная подпрограмма определения работоспособности кук — напишите сначала тест в две строчки чтобы убедиться, что вы хотя бы можете выставлять и читать куку.
2. Вывод отладочной информации.
Проверяйте значение КАЖДОЙ переменной! Каждого значения, возвращаемого функцией!
Не работает локейшен? Выведите его на экран и скопируйте в браузер!
В файл записывается пустая строка? проверяйте составляющие этой строки на каждом этапе ее создания и выводите на экран!
Убедились, что на экран выводится? Тренируйтесь писать в файл, на тестовой строке! Забитой прямо в скрипт! Уменьшайте количество неизвестных!
И всегда смотрите не то, что показывает браузер, а ИСХОДНЫЙ HTML код!

Надеюсь, что я смог хотя бы немного объяснить принципы этого занятия.
Удачной отладки.

Источник статьи: http://phpfaq.ru/debug

Бортовой журнал

Полет нормальный. Без происшествий.

Ошибки PHP: как выявить и что с ними делать?

Если у вас сайт на PHP, даже самый простой, время от времени в его скриптах могут возникать ошибки. Это может привести к различным неприятным последствиям, от некорректной работы некоторых компонентов сайта (например, формы обратной связи), до недоступности сайта целиком. Как самостоятельно распознать тип ошибки PHP и понять, что с ней делать дальше?

Этот материал поможет вам, во-первых, самостоятельно оценить ситуацию (и, возможно, даже решить ее), а во-вторых, точно ускорит диагностику и решение проблемы при обращении в службу поддержки. Самые ценные советы по устранению наиболее частых ошибок PHP, связанных с лимитами оперативной памяти, вы найдете в конце статьи.

Как обнаружить ошибку PHP на сайте

1. Встроенными средствами браузера

Итак, если на сайте вместо привычной страницы ничего не отображается (вы видите “пустую страницу”), то, вероятнее всего, в одном из скриптов возникла ошибка. В этом можно убедиться, воспользовавшись встроенными «Инструментами разработчика» вашего браузера. В каждом браузере они могут называться немного по-разному, но суть от этого не меняется.

Например, в браузере Google Chrome это вкладка Dev Tools (или «Инструменты разработчика»). В Mozilla Firefox — это расширение Firebug (его нужно установить отдельно в меню Adds On) или же вкладка Developer.

Внутри «Инструментов разработчика» нас интересует вкладка, которая называется Network (или Net, или каким-то похожим образом).

Если на странице сайта присутствует ошибка, в этой вкладке вы увидите код ответа 500 (“Internal Server Error”).

2. Если вывод сообщений об ошибках в браузер отключен

Случается, что вывод сообщений об ошибках в браузер отключён. Чтобы сообщение об ошибке отображалось в браузере, достаточно добавить в файл .htaccess в корневой директории сайта следующую строку:

Файл .htaccess вы найдете по адресу: /home/login/domains/domain.ru/public_html/, где вместо login следует подставить логин вашего аккаунта, а вместо domain.ru — домен вашего сайта.

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

Если сайтом используется, например, CMS WordPress, то отображение ошибок можно также включить, заменив в файле wp-config.php:

3. С помощью журнала ошибок PHP

Иногда по различным причинам отображать ошибки в браузере нежелательно. В этом случае лучше всего сохранять их в какой-нибудь файл, например errors.log — журнал ошибок PHP. Для этого достаточно в файле .htaccess добавить следующую строку:

php_value error_log /home/login/domains/domain.ru/log/errors.log

Здесь /home/login/domains/domain.ru/log/errors.log — это полный путь до файла, в который будут записываться ошибки PHP (если файла с таким именем нет, он будет создан автоматически при появлении ошибки).
Теперь, если мы снова зайдем на сайт с ошибкой (либо обновим страницу с ошибкой), то в errors.log будут записаны сообщения об ошибках.

Журнал ошибок PHP можно просмотреть, например, с помощью файлового менеджера в Панели управления, открыв файл errors.log:

Также можно открыть файл с ошибками и нажать кнопку “Включить автообновление”. Таким образом, новые записи в журнале можно просматривать в реальном времени.

Расшифровка ошибок PHP

Как правило, в сообщении об ошибке достаточно подробно указано где именно и при выполнении какой части кода она возникла. Например:

Здесь ошибка заключается в следующем:

Fatal error: Call to undefined function weblizar_get_options() in /home/login/domains/domain.ru/public_html/wp-content/themes/enigma/header.php on line 14

“Вызов неопределенной функции weblizar_get_options() в файле используемой на сайте темы enigma”.

Вероятнее всего, был поврежден один из файлов темы, поэтому можно восстановить только директорию темы ./wp-content/themes/enigma/ , а не всего сайта.

Что делать, в зависимости от типа ошибки PHP

Условно ошибки PHP можно разбить на 4 уровня:

Parse Error

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

1. Если вы НЕ специалист в PHP, восстановите сайт из последней резервной копии на тот момент, когда сайт работал без ошибок.

2. Если вы специалист и самостоятельно вносили правки в код сайта, вы наверняка сможете отследить синтаксическую ошибку и исправить ее. Но проще все же воспользоваться пунктом 1.

Fatal Error и Warning

Возникают, если при выполнении кода какой-то его участок не может быть выполнен (например, попытка открыть несуществующий файл). Разница между 2-ым и 3-им уровнем в том, что при получении “критической ошибки” (FATAL ERROR) выполнение скрипта завершится, а при получении “предупреждения” (WARNING) — нет.

Восстановите сайт из последней доступной резервной копии на тот момент, когда он работал без ошибок.

Notice

К этому уровню ошибок относятся различные “замечания”, суть которых обычно отображена в тексте ошибки.

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

Частые ошибки PHP и их решение

Fatal Error: Allowed Memory

Означает, что для выполнения какой-либо части кода PHP не хватает выделенной оперативной памяти. При этом лимит памяти ограничен какими-то директивами «изнутри» сайта (то есть где-либо в скриптах сайта, либо директивой memory_limit в файле .htaccess). Чтобы исправить это, измените данный лимит в большую сторону, например, в файле .htaccess.

Для этого найдите в .htaccess такую директиву:

Вместо 128M укажите желаемый размер ограничения. Обратите внимание, что символ «M» (латинская M) указывается слитно со значением.

Помните, что есть максимальные значения памяти, отведенной на выполнение скриптов PHP, предусмотенные вашим тарифом хостинга (например, на тарифах виртуального хостинга это 512 Мб, премиум — 1024 Мб). Уточните эти значения у вашего провайдера, если они не указаны явно.

Fatal Error: Out of memory

То же самое, что и предыдущая ошибка, с той разницей, что достигнут лимит памяти, заданный “снаружи”. Обратите внимание на параметр “Памяти на процесс, Мб, не более“ в условиях пользования нашим сервисом.

Для решения вопроса в данном случае, скорее всего, потребуется либо оптимизация скриптов, чтобы они потребляли меньше памяти, либо разбиение процессов на части. Например, объемную загрузку или выгрузку данных, если она упирается в данный лимит, имеет смысл производить частями.

Также в этом случае мы советуем попробовать отключить акселераторы PHP, если они у вас подключены.

Unable to allocate memory for pool

Сайтам на аккаунте не хватает выделенной на тарифном плане памяти для акселераторов PHP.

Для решения проблемы вы можете отключить использование акселераторов в Панели управления хостингом, в разделе «Управление персональным веб-сервером».

Также, например, можно отключить акселератор APC для определенного сайта, добавив в файл .htaccess корневой директории следующую директиву:

php_value apc.cache_by_default off

Обычно имеет смысл оставлять APC для использования на самом посещаемом из ваших сайтов — это позволит использовать именно на нем преимущества акселератора, не заполняя его память данными с других, менее посещаемых сайтов.

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

Мы постараемся предложить возможные варианты решения.

Источник статьи: http://blog.sprinthost.ru/2015/07/28/oshibki_php/

Как и какими средствами находить ошибки в PHP коде?

При разработке, порой, код не работает так, как задумано или вообще не работает. Сижу, гадаю: что и где не так? Посмотрев час на код — иду на проф. ресурсы, например Stack Overflow и публикую вопрос «Где здесь ошибка?» или «Почему не работает?»

В итоге часто проблема мелкая, дурацкая опечатка, ошибка в синтаксисе и прочее. Профессионалом так не станешь, если по каждой ерунде бегать по ресурсам. А я хочу им быть.

Вопрос: какие есть способы, чтобы найти ошибки в PHP коде? Какие инструменты, методы, плагины, пути и пр.?

UPD (16.10.2021): список действенных способов в текущем топике (чтобы не листать все):

7 ответов 7

Вчера всё работало, а сегодня не работает / Код не работает как задумано

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 прописываем настройки:

Перезагружаем сервер, на всякий случай.

Для 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

Примечание: каталог 20151012 , скорее всего, будет другим. cd в /usr/lib/php и проверьте, в каком каталоге в этом формате находится файл xdebug.so , и используйте этот путь. 7.0 — тоже отличается, в зависимости от того, какая версия у вас используется

Перезагружаем сервер, на всякий случай.

Теперь если в файле .php написать phpinfo(); то можно будет увидеть в самом низу такую картину:

  • нажимаем 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-запроса с формы с данными и другие действия).

  1. Стэк вызовов, все вложенные вызовы, которые привели к текущему месту кода.
  2. Переменные. На текущий момент строки ниже номера 3 ещё не выполнились, поэтому определена лишь $data
  3. Показывает текущие значения любых переменных и выражений. В любой момент здесь можно нажать на + , вписать имя любой переменной и посмотреть её значение в реальном времени. Например: $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.

Это удобно, если останов нужен только при определённом значении, а не всегда (особенно в случае с циклами).

Источник статьи: http://ru.stackoverflow.com/questions/701142/%D0%9A%D0%B0%D0%BA-%D0%B8-%D0%BA%D0%B0%D0%BA%D0%B8%D0%BC%D0%B8-%D1%81%D1%80%D0%B5%D0%B4%D1%81%D1%82%D0%B2%D0%B0%D0%BC%D0%B8-%D0%BD%D0%B0%D1%85%D0%BE%D0%B4%D0%B8%D1%82%D1%8C-%D0%BE%D1%88%D0%B8%D0%B1%D0%BA%D0%B8-%D0%B2-php-%D0%BA%D0%BE%D0%B4%D0%B5

Нарушения в работе системы 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 такие ошибки рассматриваются как достаточно серьезные для того, чтобы прекратить выполнение сценария, не задавая дополнительных вопросов. Поэтому область применения специализированных функций обработки ошибок главным образом сводится к предупреждениям. Основное назначение таких функций заключается в том, что они позволяют избежать необходимости показывать конечному пользователю сообщения об ошибках, предназначенные для программиста, и нарушать ход выполнения приложения.

Определение обработчика ошибок

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

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

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

После подготовки и выполнения такого кода все ошибки, которые разрешены в соответствии с установленной степенью серьезности регистрируемых ошибок, будут обрабатываться с помощью применяемой специализированной функции, за исключением неисправимых ошибок, которые, к сожалению, также неизбежны:

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

Инициирование пользовательской ошибки вручную

В PHP можно инициировать пользовательскую ошибку. Такая операция приблизительно эквивалентна операции активизации исключительной ситуации в версии PHP 5 (конструкция throw). Ошибка любого типа может быть инициирована путем передачи в функцию trigger_error() сообщения об ошибке и необязательной константы с обозначением степени серьезности ошибки, как в следующем примере:

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

Ведение журнала и отладка

Если средства обработки исключительных ситуаций и формирования сообщений об ошибках не применяются должным образом, то задача отладки существенно усложняется. Ошибка, которую и без того трудно выявить, может стать почти неуловимой, если программист непродуманно использует способы подавления или перенаправления сообщений об ошибках. Но достаточно лишь немного более тщательно продумать применение обработчиков ошибок, и сопровождение приложения существенно упрощается.

В приведенных выше примерах процесс обработки ошибок в основном рассматривался как средство создания интерфейса, в котором пользователь не обнаруживает следов возникших нарушений в работе. По такому же принципу можно обеспечить применение этих средств для упрощения регистрации ошибок и отладки в интересах программиста. Для этого достаточно включить вызов встроенной функции, такой как error_log(), и передать в эту функцию любую релевантную информацию, которая может помочь в процессе отладки, как в следующем коде. Следует учитывать, что в ходе разработки может потребоваться прибегнуть к использованию функции getTraceAsString(), позволяющей обеспечить ведение журналов:

Функция error_log() принимает в качестве второго параметра одно из четырех целых чисел, описание которых приведено ниже. Этот параметр задает тип сообщения в сочетании с третьим параметром, который указывает на местонахождение объекта — получателя сообщения об ошибке:

0 — сообщение, регистрируемое с использованием общесистемного механизма ведения журналов операционной системы.

1 — сообщение об ошибке, передаваемое по указанному адресу электронной почты (в качестве четвертого параметра можно ввести дополнительные заголовки).

2 — сообщение об ошибке, передаваемое через отладочное соединение PHP (должна быть разрешена дистанционная отладка).

3 — сообщение об ошибке, добавляемое в конец указанного файла журнала ошибок.

Ошибки, обнаруживаемые интерпретатором PHP

После того, как мы рассмотрели виды ошибок и способы их обработки, давайте рассмотрим наиболее распространенные нарушения при работе с PHP.

Проблемы, связанные с инсталляцией PHP

Я не стану читать мораль на тему, что не следует одним махом проходить все этапы инсталляции, не разобравшись в документации, а приведу описание нескольких часто встречающихся признаков нарушения в работе, которые обычно появляются после того, как инсталляция PHP выполняется впервые. Если вы устанавливали PHP не вручную, а например через WAMP-сервер, то приведенные ниже проблемы скорее всего у вас не возникнут.

Признак нарушения в работе: в окне браузера отображается текст файла

Если в окне браузера появляется текст сценария PHP вместо результирующего кода HTML, такая ситуация явно свидетельствует о том, что не происходит вызов машины PHP. Проверьте, что обращаетесь к сайту с помощью веб-сервера, а не файловой системы. Применяйте следующий вариант:

Если после обновления страницы вы увидите в браузере слово 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, иногда встречаются ошибки, подобные показанной ниже:

Можно считать, что это сообщение представляет собой вариант сообщения Page cannot be found (He удается найти страницу), относящийся к включаемым файлам. Появление этого сообщения свидетельствует о том, что интерпретатору PHP не удалось загрузить даже первую строку активизированного файла. Активизированный файл отсутствует, поскольку не удается найти файл с указанным именем.

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

Ошибки интерпретации

Наиболее распространенная категория ошибок возникает при обработке содержащего орфографические ошибки или синтаксически неправильного кода PHP, который вызывает сбои в работе машины интерпретации PHP.

Признак нарушения в работе — сообщение об ошибке интерпретации (Parse error)

Безусловно, количество причин возникновения проблем при интерпретации велико, но признак этого нарушения в работе почти всегда остается одинаковым — сообщение об ошибке интерпретации, Parse error:

Сообщение об ошибке интерпретации (Parse error)

Все наиболее распространенные причины ошибок интерпретации, подробно описанные ниже, являются довольно незначительными и допускают несложное исправление, особенно если учесть, что интерпретатор PHP сам подсказывает способ их исправления. Тем не менее при любой ошибке интерпретации возвращается идентичное сообщение (в котором изменяются только имена файлов и номера строк) независимо от причины. Любой код HTML, который может находиться в файле с ошибками, не отобразится или не обнаружится в исходном коде, даже если этот код находится перед фрагментом PHP, вызвавшем появление ошибки.

Отсутствие точки с запятой

Ошибка интерпретации возникает, если точка с запятой не стоит, как положено, после каждого оператора PHP. В следующем примере фрагмента PHP в первой строке отсутствует точка с запятой, поэтому операция присваивания значения переменной так и не выполняется:

Отсутствие знаков доллара

Еще одна весьма распространенная проблема состоит в том, что пропущен знак доллара, предшествующий имени переменной. Если знак доллара отсутствует в операторе присваивания переменной начального значения, как в следующем примере:

то возникает сообщение об ошибке интерпретации. Но если вместо этого знак доллара отсутствует в применяемом впоследствии операторе вывода значения переменной, как в следующем примере:

то интерпретатор PHP не выводит сообщение об ошибке интерпретации. Вместо этого в окне отображается строка «Количество: count».

Это — превосходный пример, показывающий, почему не следует рассчитывать на то, что интерпретатор PHP сообщит вам обо всех ошибках на странице. Безусловно, сообщения об ошибках PHP являются более информативными по сравнению с большинством других средств динамического формирования информационного наполнения, но ошибки, подобные указанной, вполне могут остаться незамеченными, если усилия, предпринятые при проверке правильности кода, не будут соответствовать требованиям решаемой задачи.

Если вам приходится затрачивать значительную часть времени на отладку кода PHP, то для вас может оказаться буквально бесценным редактор текста, позволяющий переходить к строкам с указанными номерами и подсвечивающий все синтаксические ошибки. Я, например, использую удобную IDE Adobe Dreamweaver, которая динамически подсвечивает синтаксические ошибки, а также содержит нумерацию строк, чтобы можно было легко найти другие виды ошибок, которые отображаются в окне браузера:

Подсветка ошибки в Adobe Dreamweaver

Подобные программы позволяют избежать большого количества синтаксических ошибок на этапе написания кода.

Проблемы, связанные со сменой режима

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

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

Кавычки, не обозначенные управляющими последовательностями

При использовании такого стиля разработки, в котором для выработки кода HTML в максимальной степени применяется код PHP, часто возникает еще одна ошибка интерпретации, связанная с тем, что кавычки в строках не обозначаются управляющими последовательностями:

Другие причины ошибок интерпретации

Проблемы, названные выше, не составляют исчерпывающий список источников ошибок интерпретации. Дело в том, что сбой в работе интерпретатора возникает под воздействием любых нарушений формата оператора 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, вызвана с меньшим или большим количеством фактических параметров по сравнению с тем, на обработку которого она рассчитана. Если задано больше параметров, чем требуется, то никаких затруднений не возникает, но если используется меньше параметров по сравнению с ожидаемым, то возникает ошибка.

Источник статьи: http://addphp.ru/materials/base/1_17.php

Отладка программ

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

Количество инструментальных средств отладки достаточно велико. Не в последнюю очередь такая ситуация объясняется тем, что в приложениях PHP обычно используются возможности нескольких серверов (таких как сервер HTTP и сервер, входящий в состав системы управления базами данных), а в комплект каждого из таких серверов обычно входят собственные компоненты ведения журналов и формирования сообщений об ошибках, с помощью которых эти серверы предоставляют своим пользователям возможность следить за происходящим.

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

Кроме встроенных средств формирования сообщений об ошибках языка PHP и технологий, поддерживаемых этим языком, программисты, работающие на языке PHP, в последнее время получили возможность использовать такие же разновидности инструментальных средств отладки, которые в течение многих лет находились в распоряжении программистов, работающих на других языках. Основной среди этих инструментальных средств является среда отладки Zend, которая позволяет контролировать значения переменных, устанавливать точки прерывания и обеспечивать пошаговое выполнение программ с любой желаемой скоростью. В этой статье среда отладки Zend не рассматривается, но ее описание и другие дополнительные сведения можно найти по адресу www.zend.com.

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

Общие стратегии поиска неисправностей

Двумя основными составляющими всей деятельности по отладке являются обнаружение причин нарушения в работе и последующее их устранение (без нарушения функционирования чего-либо иного под воздействием побочных эффектов реализации принятого решения). Это утверждение остается справедливым независимо от того, осуществляется ли диагностика программы PHP, телефонного коммутатора, электронной схемы или автомобиля «Копейка», — определенные принципы остаются в силе, о какой бы рассматриваемой проблемной области не шла речь. Всегда руководствуйтесь таким подходом, пытаясь выяснить, в чем причина нарушений в работе рассматриваемого программного обеспечения.

Внесение изменений только в одном месте

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

Ограничение области проявления проблемы

Если удастся свести поиск причин проблемы до единственной библиотеки или функции, это можно рассматривать как значительный успех в процессе поиска источника проблемы. Используйте специальные вызовы функций echo() и print_r() для своевременного вывода информации трассировки. Это позволяет определить тот момент, когда возникают изменения, являющиеся причиной нарушения в работе, и в какое время переменные приобретают такие значения, которые не должны были содержать.

Кроме того, для контроля над функционированием программ и за поведением компонентов программ в ходе их функционирования можно использовать отладчик с графическим интерфейсом (такой как Zend Studio).

Упрощение и последующее усложнение

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

Документирование принятых решений

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

Повторная проверка после исправления ошибок

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

Общая классификация ошибок

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

Ошибки на этапе компиляции

Язык PHP является компилируемым, но компиляция программы осуществляется непосредственно перед ее выполнением, поэтому сам процесс компиляции не столь очевиден, как в языке C или Java.

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

Ошибки этапа выполнения

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

Логические ошибки

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

Предположим, перед программистом поставлена задача обеспечить запуск космического зонда и вывести его на орбиту вокруг Марса. Программист из США предусмотрел в своем навигационном алгоритме получение входных данных в фунтах и дюймах, но требуемые данные поступают из европейского центра управления полетами в метрической системе. Очевидно, что при таких условиях космический зонд непременно врежется в марсианскую поверхность. Программное обеспечение действовало в полном соответствии с заданием, но, строго говоря, при таких условиях задание предусматривало вывод ракеты прямо на Марс. Это — логическая ошибка.

Из этого следует, что необходимо добиться того, чтобы программа не просто вырабатывала выходные данные, но вырабатывала их правильно. Воспользуйтесь отдельно взятой процедурой расчетов и убедитесь в том, что формируемые программой результаты являются правильными; еще один вариант состоит в том, что результаты программы должны сравниваться с заведомо известными правильными значениями. А для того чтобы не попадать в неприятную историю, не пишите программы на языке PHP для космических кораблей ;).

Использование журналов веб-сервера

Эксплуатация большинства программ PHP приводит к получению HTML-страниц того или иного рода, а эти страницы, в свою очередь, передаются пользователю с помощью HTTP-сервера, такого как Apache или Microsoft Internet Information Server (IIS). Это означает, что дополнительным источником ошибок может стать программное обеспечение веб-сервера. По этой причине важно знать, какой способ применяется в веб-сервере для формирования и регистрации сообщений об ошибках, а также знать о том, как получить доступ и провести синтаксический анализ журналов, в которых регистрируются ошибки.

Сервер Apache

На HTTP-сервере Apache ведутся два файла журнала в формате открытого текста. Эти журналы описаны ниже:

Apache/logs/access.log

Предназначен для регистрации каждого запроса на получение файла, передаваемого по протоколу HTTP. К регистрируемым данным относятся дата, время и полученные результаты (успешное или неудачное завершение, о чем можно судить по числовому коду состояния). Этот журнал представляет собой также журнал регистрации доступа, в котором фиксируется IP-адрес, из которого поступил каждый запрос.

Apache/logs/error.log

Это — журнал регистрации ошибок, в котором фиксируются только ситуации, связанные с возникновением ошибок.

Унифицированный формат журнала

По умолчанию для оформления записей в файле error.log сервера Apache используется унифицированный формат журнала, который принят в качестве стандартного. В этом формате каждая запись соответствует отдельному экземпляру действия, касающегося запроса и/или ответа (в конечном итоге HTTP-серверы занимаются обработкой именно запросов и ответов). Например, одна строка журнала может соответствовать запросу на получение HTML-страницы (и содержать сведения о том, в каких обстоятельствах эта страница была впоследствии предоставлена сервером Apache). А следующая строка может описывать (автоматическое) выполнение запроса и передачу файла JPEG, связанного с ранее затребованным документом HTML.

В любом случае записи в унифицированном формате журнала выглядят примерно так, как показано ниже (в действительности каждая запись занимает только одну строку):

Ниже перечислены наиболее важные компоненты данной строки:

127.0.0.1. IP-адрес клиента, от которого поступил запрос по протоколу HTTP (в данном случае локальный хост).

[12/Jan/2013:03:18:33 +0400]. Дата, время и разница между временем текущего часового пояса и всеобщим скоординированным временем (Universal Coordinated Time — UTC).

GET. Тип запроса HTTP — GET или POST.

/images/lang.gif. Затребованный файл.

HTTP/1.1. Версия протокола HTTP, используемого для передачи запроса.

200. Код ответа, описывающий результат запроса (дополнительная информация на эту тему приведена ниже в данном разделе).

6590. Количество байтов, переданных в ответе HTTP, соответствующем этому запросу.

Коды ответов HTTP

Количество кодов ответов HTTP весьма велико (хотя самым знаменитым остается код сообщения об ошибке «404 Not Found»), но сами эти коды подчиняются общему шаблону, с помощью которого можно быстро узнать назначение каждого кода. По существу, данные шаблоны подразделяются на категории, описанные ниже:

Коды ряда 200 указывают на успешное завершение.

Коды ряда 300 обозначают перенаправление.

Коды ряда 400 указывают на клиентскую ошибку (подобную указанию в запросе несуществующего документа).

Коды ряда 500 указывают на серверную ошибку.

Полный список кодов ответов HTTP приведен по адресу www.w3.org/Protocols/rfc2616/rfc2616-sec10.html.

Сервер IIS

В HTTP-сервере IIS компании Microsoft задача ведения журнала осуществляется иначе. Сервер IIS не записывает журнал в файл, а регистрирует полученную им информацию о состоянии и об обнаруженных ошибках таким образом, чтобы эта информация была доступна для исследования в программе Event Viewer. Ошибки, зарегистрированные сервером IIS, можно найти в части System Log окна Event Viewer, где для обозначения источника применяется имя W3SVC.

Средства формирования сообщений об ошибках и ведения журнала интерпретатора PHP

Неоценимую помощь при выявлении ошибок может оказать сам интерпретатор PHP. Даже без какой-либо дополнительной настройки система PHP способна выводить сообщения об ошибках вместе с выходными данными. Эти сообщения передаются прямо в окно браузера вместе с номерами строк. Для большинства программистов этих сведений вполне достаточно, чтобы можно было воспользоваться самим интерпретатором PHP как средством отладки, но, чтобы получить максимум пользы от этих средств, важно знать все нюансы настройки конфигурации, от которых зависят условия формирования сообщений об ошибках.

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

Формирование сообщений об ошибках

Выполняемая интерпретатором PHP операция включения сообщения об ошибке в вывод программы (что чаще всего приводит к отображению сообщения об ошибке в окне браузера) по существу представляет собой операцию формирования сообщения об ошибке. Формирование сообщений об ошибках является полезным диагностическим инструментальным средством, использование которого разрешено по умолчанию. Если же интерпретатор PHP подключен к серверу производственного назначения, то данное средство должно быть запрещено.

Чтобы разрешить или запретить формирование сообщений об ошибках, необходимо внести изменение в файл php.ini. При этом корректировка применяется к параметру display_errors. Если требуется, чтобы сообщения выводились в составе формируемых выходных данных, то в файле php.ini должна присутствовать следующая строка:

Если же сообщения об ошибках не должны отображаться (и это действительно не допустимо, если сервер используется для предоставления к нему общего доступа), то соответствующая строка должна выглядеть таким образом:

Игнорирование данной рекомендации при эксплуатации сервера производственного назначения приводит к тому, что функционирование средств формирования сообщений об ошибках вызовет непреднамеренное раскрытие перед пользователями важных сведений об организации программного обеспечения. Например, какое-либо непредвиденное условие может вызвать появление в окне незащищенного браузера имени переменной или таблицы базы данных. А потенциальный нарушитель сможет воспользоваться этой информацией для несанкционированного доступа к серверу.

Регистрация ошибок

Регистрация ошибок аналогична по своему назначению формированию сообщений об ошибках, но предусматривает запись информации о событиях, связанных с ошибками, в текстовый файл, а не вывод этой информации на экран. Такой вариант представления сведений об ошибках более приемлем с точки зрения защиты. Кроме того, поскольку файлы журналов должны храниться в каталоге с ограниченным доступом, этот метод регистрации ошибок более предпочтителен для использования на HTTP-серверах производственного назначения.

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

В противном случае следует задать такую опцию:

По умолчанию средства регистрации ошибок запрещены в файле php.ini.

Определение категории ошибок, подлежащих выводу на экран или записи в журнал

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

Такая настройка указывает, что пользователю должна предоставляться информация обо всех ошибках и предупреждениях (что показывает параметр E_ALL), но вместе с тем действует условие (что показывает оператор &), согласно которому извещения этапа прогона не подлежат выводу (для этого служит параметр

представляет собой оператор отрицания).

Степень серьезности отображаемых сообщений об ошибках, которая определена параметром error_reporting, отражается на поведении средств регистрации ошибок (если их использование разрешено с помощью параметра log_errors=On) и средств формирования сообщений об ошибках (если их использование разрешено с помощью параметра display_errors=On) или одновременно тех и других средств, если все они разрешены.

Функции формирования сообщений об ошибках

Язык PHP не только в значительной степени упрощает работу программистов, но и включает в себя широкий набор функций, которые могут использоваться программистами для облегчения поиска причин нарушений в работе и в целом для получения сведений обо всех аспектах состояния разрабатываемых ими программ. Спектр таких средств начинается с обычных операторов формирования вывода (print, echo и тому подобных), используемых в тех контекстах, когда требуется контролировать значения переменных, и заканчивается специализированными функциями, осуществляющими вывод данных с помощью механизмов ведения журналов операционной системы.

В настоящем разделе даны вводные сведения о некоторых функциях PHP, которые позволяют выявлять причины проблем и создавать отчеты об условиях функционирования программ.

Диагностические операторы вывода

Простейший метод устранения нарушений в работе предусматривает размещение в ключевых местах кода операторов echo и print, для того чтобы формируемые выходные данные содержали информацию о ходе выполнения программы, осуществляемого на основе вызова различных функций, а также о том, какие значения принимают наиболее важные переменные в различных точках.

Использование таких средств можно сравнить с применением простейшего отладчика, поскольку операторы вывода позволяют отслеживать значения переменных во время выполнения программы и следить за тем, не происходит ли присваивание этим переменным каких-либо непредусмотренных значений (и в случае положительного ответа на этот вопрос позволяют узнать, когда это происходит).

Использование функции var_dump()

Обычные функции вывода являются довольно удобными, но с точки зрения отладки более специализированные функции может оказаться гораздо полезнее. Наиболее важной среди функций подобного типа является функция var_dump(). Она может рассматриваться как чрезвычайно «остроумный» оператор вывода, который, кроме всего прочего, автоматически представляет содержимое любого массива в таком виде, который очень удобен для восприятия человеком.

Напомним, что выполнение приведенного ниже кода приводит к получению результатов, от которых мало пользы:

Данные результаты сводятся к следующему:

Использование конструкции echo для вывода массива

Это нам ничего не дает. С другой стороны, если за определением того же массива следует строка

то формируется следующие намного более полезные выходные данные:

Использование функции var_dump() для вывода массива

На основании таких данных программист, занимающийся отладкой, может немедленно определить, каково содержимое данного массива (чему равны ключи и значения элементов этого массива).

Использование функции syslog()

В языке PHP предусмотрена функция syslog(), которая позволяет осуществлять запись непосредственно в журнал операционной системы, под управлением которой функционирует среда PHP. Это удобная функция, которая становится особенно полезной, если требуется регистрировать всю информацию о проблемах, возникающих в системе, с помощью стандартных средств, или есть необходимость предупредить о нарушении в работе системного администратора, если он непосредственно не соприкасается с разработками на языке PHP.

В целом функция syslog() позволяет указать степень серьезности, связанную с регистрируемым событием, а также ввести сообщение, которое описывает это событие. Затем указанные значения могут быть выведены в журнал для использования в качестве вспомогательной информации для диагностики.

Все возможные опции определения степени серьезности функции syslog() показаны в следующем коде:

В системе Microsoft Windows первые три из этих сообщений об ошибках (от LOG_DEBUG до LOG_NOTICE) рассматриваются как информационные, четвертое и пятое считаются предупреждающими, а последние три отмечаются в программе Event Viewer как относящиеся к категории Alerts. Все эти сообщения отображаются со значением источника c-client, которое соответствует одному из вспомогательных процессов сервера Apache:

Сообщения об ошибках с различными степенями серьезности в программе Event Viewer

Использование функции error_log()

Функция error_log() может использоваться для передачи сообщения об ошибке почти в любое место назначения, включая адрес электронной почты. Эта функция предоставляет легкий и удобный способ формирования отчета о непредвиденных условиях, возникших в процессе функционирования программного обеспечения PHP, но, к сожалению, этим средством пользуются лишь немногие разработчики. Более подробно она описана в предыдущей статье в разделе «Ведение журнала и отладка».

Источник статьи: http://addphp.ru/materials/base/1_18.php

Ошибки PHP: классификация, примеры, обработка

В статье представлена очередная попытка разобраться с ошибками, которые могут встретиться на вашем пути php-разработчика, их возможная классификация, примеры их возникновения, влияние ошибок на ответ клиенту, а также инструкции по написанию своего обработчика ошибок.

Классификация ошибок

Примеры возникновения ошибок

Примечание: для полной работоспособности скрипта необходим PHP версии не ниже 5.3.0.

В файле errors.php представлены выражения, инициирующие практически все возможные ошибки. Исключение составили: E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_WARNING, генерируемые ядром Zend. В теории, встретить их в реальной работе вы не должны.
В следующей таблице приведены варианты поведения этого скрипта в различных условиях (в зависимости от значений директив display_errors и error_reporting):

Группа ошибок Значения директив * Статус ответа сервера Ответ клиенту **
E_PARSE, E_COMPILE_ERROR *** display_errors = off
error_reporting = ANY
500 Пустое значение
display_errors = on
error_reporting = ANY
200 Сообщение об ошибке
E_USER_ERROR, E_ERROR, E_RECOVERABLE_ERROR display_errors = off
error_reporting = ANY
500 Вывод скрипта до ошибки
display_errors = on
error_reporting = ANY
200 Сообщение об ошибке и вывод скрипта до ошибки
Не фатальные ошибки display_errors = off
error_reporting = ANY
и
display_errors = on
error_reporting = 0
200 Весь вывод скрипта
display_errors = on
error_reporting = E_ALL | E_STRICT
200 Сообщение об ошибке и весь вывод скрипта

* Значение ANY означает E_ALL | E_STRICT или 0.
** Ответ клиенту может отличаться от ответов на реальных скриптах. Например, вывод какой-либо информации до включения файла errors.php, будет фигурировать во всех рассмотренных случаях.
*** Если в файле errors.php заменить пример для ошибки E_COMPILE_ERROR на require «missing_file.php»; , то ошибка попадет во вторую группу.

Значение, приведенной выше, таблицы можно описать следующим образом:

  1. Наличие в файле скрипта ошибки, приводящей его в «негодное» состояние (невозможность корректно обработать), на выходе даст пустое значение или же только само сообщение об ошибке, в зависимости от значения директивы display_errors.
  2. Скрипт в файле с фатальной ошибкой, не относящейся к первому пункту, будет выполняться в штатном режиме до самой ошибки.
  3. Наличие в файле фатальной ошибки при display_errors = Off обозначит 500 статус ответа.
  4. Не фатальные ошибки, как и следовало ожидать, в контексте возможности исполнения скрипта в целом, на работоспособность не повлияют.

Собственный обработчик ошибок

Для написания собственного обработчика ошибок необходимо знать, что:

  • для получения информации о последней произошедшей ошибке существует функция error_get_last();
  • для определения собственного обработчика ошибок существует функция set_error_handler(), но фатальные ошибки нельзя «перехватить» этой функцией;
  • используя register_shutdown_function(), можно зарегистрировать свою функцию, выполняемую по завершении работы скрипта, и в ней, используя знания из первого пункта, если фатальная ошибка имела место быть, предпринять необходимые действия;
  • сообщение о фатальной ошибке в любом случае попадет в буфер вывода;
  • воспользовавшись функциями контроля вывода можно предотвратить отображение нежелательной информации;
  • при использовании оператора управления ошибками (знак @) функция, определенная в set_error_handler() все равно будет вызвана, но функция error_reporting() в этом случае вернет 0, чем и можно пользоваться для прекращения работы или определения другого поведения своего обработчика ошибок.

Третий пункт поясню: зарегистрированная нами функция при помощи register_shutdown_function() выполнится в любом случае — корректно ли завершился скрипт, либо же был прерван в связи с критичной (фатальной) ошибкой. Второй вариант мы можем однозначно определить, воспользовавшись информацией предоставленной функцией error_get_last(), и, если ошибка все же была, выполнить наш собственный обработчик ошибок.
Продемонстрируем вышесказанное на модифицированном скрипте index.php:

Не забываем, что ошибки смешанного типа, после объявления собственного обработчика ошибок, стали не фатальными. Плюс к этому, весь вывод скрипта до фатальной ошибки вместе с стандартным сообщением об ошибке будет сброшен.

Вообще, рассмотренный пример обработчика ошибок, обработкой, как таковой, не занимается, а только демонстрирует саму возможность. Дальнейшее его поведение зависит от ваших желаний и/или требований. Например, все случаи обращения к обработчику можно записывать в лог, а в случае фатальных ошибок, дополнительно, уведомлять об этом администратора ресурса.

Источник статьи: http://habr.com/ru/post/161483/

Ищем баги в PHP коде без статических анализаторов

Моя самая любимая часть в статическом анализе кода — это выдвижение гипотез о потенциальных ошибках в коде с последующей их проверкой.

Но есть вероятность, что даже на нескольких миллионах строк кода подобная диагностика не «выстрелит», поэтому на неудачные гипотезы тратить много времени не хочется.

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

  • Поиск и разбор багов в open source проектах.
  • Quick start по phpgrep.
  • Принцип работы синтаксического поиска.

Предпосылки

Вот уже несколько месяцев я занимаюсь поддержкой PHP линтера NoVerify (почитать о котором можно в статье NoVerify: линтер для PHP от Команды ВКонтакте).

Время от времени в команде появляются идеи для новых диагностик. Идей может быть много, а проверить хочется все, особенно если предложенная проверка нацелена на выявление критических дефектов.

Ранее я активно разрабатывал go-critic и ситуация была схожей, с той лишь разницей, что анализировались исходники на Go, а не на PHP. Когда я узнал об утилите gogrep, мой мир перевернулся. Как видно из названия, эта утилита имеет что-то общее с grep’ом, только поиск производится не по регулярным выражениям, а по синтаксическим шаблонам (позже объясню, что это значит).

Я уже не хотел жить без умного grep, поэтому в один вечер решил сесть и написать phpgrep .

Анализируемый корпус

Чтобы было увлекательно, мы сразу погрузимся в применение. Будем анализировать небольшой набор достаточно известных и крупных PHP проектов, доступных на GitHub.

В наш набор попали следующие проекты:

Для людей, которые замышляют то, что мы с вами замышляем, это очень аппетитный набор.

Использование присваивания в качестве выражения

Если присваивание используется как выражение, причём:

  • контекст ожидает результат логической операции (логическое условие) и
  • правая часть выражения не имеет побочных эффектов и является константной,

то, скорее всего, в коде ошибка.

Для начала, возьмём за «логический контекст» следующие конструкции:

  1. Выражение внутри » if ($cond) «.
  2. Условие тернарного оператора: » $cond ? $x : $y «.
  3. Условия продолжений циклов » while ($cond) » и » for ($init; $cond; $post) «.

В правой части присваивания мы ожидаем константы или литералы.

Оба ограничения нужны для уменьшения количества ложных срабатываний.

Если мы ищем присваивания исключительно внутри условий, то вероятность, что имела место опечатка и вместо «=» подразумевался «==», выше.

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

Здесь мы видим 4 шаблона, единственным различием между которыми выступает присваиваемое выражение (RHS). Начнём с первого из них.

Шаблон » if ($_ = []) $_ » захватывает if , у которого любому выражению присваивается пустой массив. $_ сопоставляется с любым expression или statement.

В следующих примерах используются более сложные группы const, str и num. В отличие от $_ они описывают ограничения на совместимые операции.

  • const — именованная константа или константа класса.
  • str — строковой литерал любого типа.
  • num — числовой литерал любого типа.

Этих шаблонов достаточно, чтобы добиться нескольких срабатываний на корпусе.

Вторым срабатыванием в moodle стала зависимость ADOdb. В upstream библиотеки проблема всё ещё присутствует.

В этом фрагменте прекрасно многое, но для нас релевантна только первая строка. Вместо сравнения поля databaseType мы выполняем присваивание и всегда входим внутрь условия.

Ещё одно интересное место, где мы хотим выполнять действия только для «корректных» записей, но, вместо этого, выполняем их всегда и, более того, отмечаем любую запись как корректную!

Повторим то, что мы изучили:

  • Шаблоны выглядят как PHP-код, который они находят.
  • $_ обозначает «что угодно». Можно сравнить с . в регулярных выражениях.
  • $ <" ">работает как $_ с ограничением на тип элементов AST.

Стоит ещё подчеркнуть, что всё, кроме переменных, сопоставляется дословно (literally). Это значит, что шаблону » array(1, 2 + 3) » будет удовлетворять лишь идентичный по синтаксической структуре код (пробелы не влияют). С другой стороны, шаблону » array($_, $_) » удовлетворяет любой литерал массива из двух элементов.

Сравнение выражения с самим собой

Потребность сравнить что-либо с самим собой возникает очень редко. Это может быть проверка на NaN , но как минимум в половине случаев это ошибка copy/paste.

Справа должно быть » $fv2->month «.

Для выражения повторяющихся частей в шаблоне мы используем переменные с именами, отличными от » _ «. Механизм повторений в шаблоне похож на обратные ссылки в регулярных выражениях.

Шаблон » $x == $x » будет как раз тем, что найдёт пример выше. Вместо » x » может использоваться любое имя. Здесь важно лишь то, чтобы имена были идентичны. Переменные шаблона, которые имеют различающиеся имена, не обязаны иметь совпадающее содержимое при захвате.

Следующий пример найден с помощью » $x «.

Дублирующиеся подвыражения

Теперь, когда мы знаем про возможности повторяемых подвыражений, мы можем составить множество любопытных шаблонов.

Один из моих любимцев — » $_ ? $x : $x «.
Это тернарный оператор, у которого true/false ветки идентичны.

Обе ветви дублируются, что подсказывает о потенциальной проблеме в коде. Если мы посмотрим на код вокруг, то сможем понять, что там должно было быть вместо этого. В угоду читабельности я вырезал часть кода и сократил название переменной $encrypted до $enc .

Я бы поставил на то, что коду необходим следующий патч:

Опасные приоритеты операций в PHP

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

Во многих языках программирования выражение » x & mask != 0 » имеет интуитивный смысл. Если mask описывает какой-то бит, то данный код проверяет, что в x этот бит не равен нулю. К сожалению, для PHP это выражение будет вычисляться так: » x & (mask != 0) «, что почти всегда не то что вам нужно.

WordPress, Joomla и moodle используют SimplePie.

SIMPLEPIE_FILE_SOURCE_REMOTE определён как 1 , поэтому выражение будет эквивалентно:

Продолжая тему неожиданных приоритетов операций, вы можете почитать про тернарный оператор в PHP. На хабре этому даже посвятили статью: Порядок выполнения тернарного оператора.

Можно ли такие места найти с помощью phpgrep ? Ответ: да!

Прелести проверки URL с помощью регулярных выражений

По задумке автора кода, мы проверяем URL на совпадение с одним из 3-х вариантов. К сожалению, символ . не экранирован, что приведёт к тому, что вместо falloutvault.com мы можем завести себе falloutvaultxcom на любом домене и пройти проверку.

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

Найти такие места можно с помощью запуска phpgrep :

Мы вводим именованный подшаблон pat , который захватывает любой строковой литерал, а затем применяем к нему фильтр из регулярного выражения.

Фильтры можно применять к любой переменной шаблона. Кроме регулярных выражений есть также структурные операторы = и != . Полный список можно найти в документации.

$ <"*">захватывает произвольное количество любых аргументов, поэтому нам можно не волноваться за опциональные параметры функции preg_match .

Дубликаты ключей в литерале массива

В PHP вы не получите никакого предупреждения, если выполните этот код:

Мы можем найти такие массивы с помощью phpgrep :

Этот шаблон можно расшифровать так: «литерал массива, в котором есть хотя бы два идентичных ключа в произвольной позиции». Выражения $ <"*">помогают нам описать «произвольную позицию», допуская 0-N элементов до, между и после интересующих нас ключей.

В данном случае это не является грубой ошибкой, но мне известны случаи, когда дублирование ключей в крупных (100+ элементов) массивах несло как минимум неожиданное поведение, в котором один из ключей перекрывал значение другого.

На этом наш краткий экскурс на примерах окончен. Если вам хочется ещё, в конце статьи описано, как получить все результаты.

Что же такое phpgrep?

Большая часть редакторов и IDE используют для поиска кода (если это не поиск по специальному символу типа класса или переменной) обычный текстовой поиск — проще говоря, что-то вроде grep’а.

Вы вводите » $x «, находите » $x «. Вам могут быть доступны регулярные выражения, тогда вы можете пытаться, по сути, парсить PHP-код регулярками. Иногда это даже работает, если ищется что-то вполне определённое и простое — например, «любая переменная с некоторым суффиксом». Но если эта переменная с суффиксом должна быть частью другого составного выражения, возникают трудности.

phpgrep — это инструмент для удобного поиска PHP-кода, который позволяет искать не с помощью text-oriented регулярок, а с помощью syntax-aware шаблонов.

Syntax-aware означает, что язык шаблонов отражает целевой язык, а не оперирует отдельными символами, как это делают регулярные выражения. Нам также нет никакой разницы до форматирования кода, важна лишь его структура.

Quick start

Установка

Для amd64 есть готовые релизные сборки под Linux и Windows, но если у вас установлен Go, то достаточно одной команды, чтобы получить свежий бинарник под вашу платформу:

Если $GOPATH/bin находится в системном $PATH , то команда phpgrep станет сразу же доступной. Чтобы это проверить, попробуйте запустить команду с параметром -help :

Если же ничего не происходит, найдите, куда Go установил бинарник и добавьте его в переменную окружения $PATH .

Старый и надёжный способ посмотреть $GOPATH , даже если он не выставлен явно:

Использование

Создайте тестовый файл hello.php :

Мы нашли все вызовы функции f с одним аргументом-числом, значение которого не равно 20.

Как работает phpgrep

Для разбора PHP используется библиотека github.com/z7zmey/php-parser. Она достаточно хороша, но некоторые ограничения phpgrep следуют из особенностей используемого парсера. Особенно много трудностей возникает при попытках нормально работать со скобочками.

Принцип работы phpgrep прост:

  • строится AST из входного шаблона, разбираются фильтры;
  • для каждого входного файла строится полное AST-дерево;
  • обходим AST каждого файла, пытаясь найти такие поддеревья, которые совпадают с шаблоном;
  • для каждого результата применяется список фильтров;
  • все результаты, которые прошли фильтры, печатаются на экран.

Самое интересное — это как именно сопоставляются на равенство два AST-узла. Иногда тривиально: один-к-одному, а мета-узлы могут захватывать более одного элемента. Примерами мета-узлов является $ <"*">и $ <"str">.

Заключение

Было бы нечестно говорить о phpgrep , не упомянув structural search and replace (SSR) из PhpStorm. Они решают похожие задачи, причём у SSR есть свои преимущества, например, интеграция в IDE, а phpgrep может похвастаться тем, что является standalone программой, которую гораздо проще поставить, например, на CI.

Помимо прочего, phpgrep — это ещё и библиотека, которую можно использовать в своих программах для матчинга PHP кода. Особенно это полезно для линтеров и кодогенерации.

Буду рад, если этот инструмент будет вам полезен. Если же эта статья просто мотивирует вас посмотреть в сторону вышеупомянутого SSR, тоже хорошо.

Дополнительные материалы

Полный список шаблонов, который был использован для анализа, можно найти в файле patterns.txt. Рядом с этим файлом можно найти скрипт phpgrep-lint.sh , упрощающий запуск phpgrep со списком шаблонов.

В статье не дан полный список срабатываний, но вы можете воспроизвести эксперимент, произведя клонирование всех названых репозиториев и запустив phpgrep-lint.sh на них.

Черпать вдохновение на шаблоны проверок можно, например, из статей PVS studio. Мне очень понравилась Logical Expressions: Mistakes Made by Professionals, которая трансформируется во что-то такое:

Вам также может быть интересна презентация phpgrep: syntax-aware code search.

В статье используются изображения гоферов, которые были созданы через gopherkon.

Источник статьи: http://habr.com/ru/post/464893/

Коды ошибок в PHP, их вывод и ловля на живца с помощью недосыпания

От автора: я опять сегодня не выспался! Вчера отлавливал ошибки в написанном скрипте, а сегодня комар жужжал под ухом всю ночь. И кажется, что это насекомое сродни тому багу, который я прошлой ночью еле нашел. В общем, сегодня (раз уж мне не спится) узнаем о кодах ошибок в PHP.

Если их не видно

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

Их вывод отключен хостером специально – таким образом он заботится о повышении безопасности своего серверного пространства. В том числе и вашего ресурса. И все потому, что в описаниях некоторых ошибок отладчик выводит конфиденциальную информацию. Умелый хакер сможет легко использовать ее для взлома вашего сайта. Например, при указании неправильного пароля при подключении к базе, расположенной на сервере MySQL. В результате на экран выводится описание ошибки, содержащее логин активного пользователя СУБД.

Бесплатный курс по PHP программированию

Освойте курс и узнайте, как создать веб-приложение на PHP с полного нуля

Все эти «частные» случаи мы рассматривали в одном из наших предыдущих материалов. Но так как нами используется Денвер, то я кратко опишу решение данной проблемы в нем.

Перед тем, как найти ошибку коде PHP, сначала нужно ее вывести на экран. Если это не происходит, тогда прямая дорога в php.ini.Здесь нужно активировать значения нескольких параметров:

Данные настройки расположены в разделе «Error handling and logging».

Логов нет!

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

В Денвере данная функция (по умолчанию) отключена. Это можно легко исправить, прописав нужный код в конфигурационном файле (в том же разделе).

Снова откройте php.ini и внесите в него выделенные ниже строки. Точнее, одна из них уже должна быть, но лучше проверить. С помощью этих директив (log_errors и error_log) разрешается запись сообщений обо всех ошибках. А также задается путь к файлу логов, с помощью которого вы сможете осуществить PHP проверку кода на ошибки.

Бесплатный курс по PHP программированию

Освойте курс и узнайте, как создать веб-приложение на PHP с полного нуля

После редактирования конфигурационного файла перезапустите локальный сервер, чтобы все изменения вступили в силу.

Проверяем

Теперь проверим, что у нас вышло. Для этого запустим умышленную синтаксическую неточность в коде: неправильно объявим переменную PHP.

Источник статьи: http://webformyself.com/kody-oshibok-v-php-ix-vyvod-i-lovlya-na-zhivca-s-pomoshhyu-nedosypaniya/

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *