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

1,00
р.
В текущем топике собран список способов по нахождению ошибок в коде, как синтаксических, так и логичеких (ошибок нет, но программа работает не так, как задумано).
В двух словах, чтобы разобраться, почему ваш код не работает, необходимо:
Убедиться, что вы видите все сообщения об ошибках, которвые выдаёт ваш код. Если сообщения есть, то заняться их исправлением. Если ошибок нет, но код всё равно работает неправильно, необходимо выполнить пошаговую отладку кода. Это можно делать как вручную, "дедовским способом", так и с помощью специальных средств отладки.
Ниже представлены рекомендации по различным вариантам отладки и решения для самых распространённых проблем:
Ничего не видно. Страница пустая и белая. | Код не запускается или выводится код как он есть в PHP
Debugging (Отладка)
Debugging (Ubuntu + >=PHP8.0 + xdebug 3.0 + PHPStorm)
Локально работает, а на хостинге нет / У XXX работает, а у YYY нет (про логирование)
Что означает эта ошибка? (parse, syntax, warning, fatal)
PHP parseyntax errors Ошибки Unexpected XXX и как решить их
Статические анализаторы


Ответ
Вчера всё работало, а сегодня не работает / Код не работает как задумано
или
Debugging (Отладка)
(см. также Настройка отладки в 2024 г: PHP8 + xdebug3 + Ubuntu + PHPStorm)

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

Важное замечание:
Есть много IDE и редакторов кода, которые позволяют производить отладку. Процесс настройки в них у всех различается. Поэтому стОит обратиться к документации по настройке отладки для непосредственно той среды разработки и той версии, в которой работаете именно ВЫ.
На текущий момент будет рассмотрен пример с PHPStorm 2017.

Подготовка
Для начала необходимо, чтобы в PHP имелась библиотека для отладки под названием xdebug. Если её еще нет, то надо установить.
ВАЖНО! Для очень новых версий PHP (например 8), требуется и новый xdebug, а он, в свою очередь, работает на порту 9003. Не пропустите указание правильного порта в IDE!! (Примерно в разделе PHP -> Debug -> Debug Port . Где точно - зависит от конкретной IDE)
Для WINDOWS:
скачать dll, например на xdebug.org.
Обычно все библиотеки лежат в папке ext внутри папки PHP. Туда и надо поместить dll.
Далее в php.ini прописываем настройки:
[Xdebug] zend_extension="C:erver/php/ext/php_xdebug.dll" // <!-- тут свой путь до dll!!! Это для среды Windows. Для Linux путь должен быть что-то типа zend_extension=/usr/lib/php/20151012/xdebug.so xdebug.default_enable = 1 xdebug.remote_enable = 1 xdebug.remote_handler = "dbgp" xdebug.remote_host = "localhost" xdebug.remote_port = 9000 xdebug.auto_trace = 0 //xdebug.mode=debug // При отладке >=php8.0
Перезагружаем сервер, на всякий случай.
Для UBUNTU:
sudo apt update ИЛИ sudo apt-get update
sudo apt install php-xdebug или если нужнен отладчик для конкретной версии PHP, то sudo apt install php7.0-xdebug где 7.0 указывается версия PHP
sudo nano /etc/php/7.0/mods-available/xdebug.ini вписываем строки: zend_extension=/usr/lib/php/20151012/xdebug.so xdebug.remote_autostart = 1 xdebug.remote_enable = 1 xdebug.remote_handler = dbgp xdebug.remote_host = 127.0.0.1 xdebug.remote_log = /tmp/xdebug_remote.log xdebug.remote_mode = req //xdebug.mode=debug // При отладке >=php8.0
Примечание: каталог 20151012, скорее всего, будет другим. cd в /usr/lib/php и проверьте, в каком каталоге в этом формате находится файл xdebug.so, и используйте этот путь. 7.0 - тоже отличается, в зависимости от того, какая версия у вас используется
Перезагружаем сервер, на всякий случай.


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

Открываем PHPStorm
нажимаем create project from existing files выбираем Web server is installed locally, source files are located under its document root выбираем папку с файлами, и нажав вверху кнопку "Project Root" помечаем папку как корень проекта нажимаем "Next" нажимаем Add new local server

вводим имя сервера любое и Web Server root URL. В рассматриваемом примере это http://localhost/testy2

нажимаем "Next" и затем "Finish"

Запуск
Для начала в левой части панели с кодом на любой строке можно кликнуть ЛКМ, тем самым поставив точку останова (breakpoint - брейкпойнт). Это то место, где отладчик автоматически остановит выполнение PHP, как только до него дойдёт. Количество breakpoint'ов не ограничено. Можно ставить везде и много.

Если кликнуть ПКМ и во всплывающем меню выбрать Debug (или в верхнем меню - Run → Debug), то при первом запуске PHPStorm попросит настроить интерпретатор. Т.е. надо выбрать версию PHP из папки, где он лежит, чтобы шторм знал, какую версию он будет отлаживать.

Теперь можно нажать Debug!!!
В данном случае, т.к. функция вызывается сразу на той же странице, то при нажатии кнопки Debug — отладчик моментально вызовет функцию, выполнение "заморозится" на первом же брейкпойнте. В ином случае, для активации требуется исполнить действие, при котором произойдет исполнение нужного участка кода (клик на кнопку, передача POST-запроса с формы с данными и другие действия).

Цифрами обозначены:
Стэк вызовов, все вложенные вызовы, которые привели к текущему месту кода. Переменные. На текущий момент строки ниже номера 3 ещё не выполнились, поэтому определена лишь $data Показывает текущие значения любых переменных и выражений. В любой момент здесь можно нажать на +, вписать имя любой переменной и посмотреть её значение в реальном времени. Например: $data или $nums[0], а можно и $nums[i] и item['test']['data'][$name[5]][$info[$key[1]]] и т.д. На текущий момент строки ниже номера 3 ещё не выполнились, поэтому $sum и $output обозначены красным цветом с надписью "cannot evaluate expression".
Процесс
Для самого процесса используются элементы управления (см. изображение выше, выделено зеленым прямоугольником) и немного из дополнительно (см. изображение выше, выделено оранжевым прямоугольником).

Show Execution Point (Alt+F10) — переносит в файл и текущую линию отлаживаемого скрипта. Например, если файлов много, решили посмотреть что в других вкладках, а потом забыли где у вас отладка :)
Step Over (F8) — делает один шаг, не заходя внутрь функции. Т.е. если на текущей линии есть какая-то функция, а не просто переменная со значением, то при клике данной кнопки, отладчик не будет заходить внутрь неё.
Step Into (F7) — делает шаг. Но в отличие от предыдущей, если есть вложенный вызов (например функция), то заходит внутрь неё.
Step Out (Shift+F8) — выполняет команды до завершения текущей функции. Удобно, если случайно вошли во вложенный вызов и нужно быстро из него выйти, не завершая при этом отладку.
Rerun (Ctrl+F5) — перезапускает отладку.
Resume Program(F9) — продолжает выполнение скрипта с текущего момента. Если больше нет других точек останова, то отладка заканчивается и скрипт продолжает работу. В ином случае работа прерывается на следующей точке останова.
Stop (Ctrl+F2) — завершает отладку.
View Breakpoints (Ctrl+Shift+F8) — просмотр всех установленных брейкпойнтов.
Mute Breakpoints — отключает брейкпойнты.
...
Итак, в текущем коде видно значение входного параметра:
$data = "23 24 11 18" — строка с данными через пробел $nums = (4) ["23", "24", "11", "18"] — массив, который получился из входной переменной.

Если нажмем F8 2 раза, то окажемся на строке 7 во вкладках Watches и Variables и в самой странице с кодом увидим, что переменная $sum была инициализирована и её значение равно 0.
Если теперь нажмем F8, то попадем внутрь цикла foreach и, нажимая теперь F8, пока не окончится цикл, можно будет наблюдать на каждой итерации, как значения $num и $sum постоянно изменяются. Тем самым мы можем проследить шаг за шагом весь процесс изменения любых переменных и значений на любом этапе, который интересует.
Дальнейшие нажатия F8 переместят линию кода на строки 11, 12 и, наконец, 15.

Дополнительно
Если нажать на View Breakpoints в левой панели, то можно не только посмотреть все брейкпойнты, но в появившемся окне можно еще более тонко настроить условие, при котором на данной отметке надо остановиться. В функции выше, например, нужно остановиться только когда $sum превысит значение 20.

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