По старинке, но проще!
Многих разработчиков выражение «отладка кода» вызывает неприятные чувства, как то, что мы не любим делать. Однако на деле это может оказаться даже увлекательной игрой, все дело в выбранных средствах. В конце концов на дворе XXI век и удобных средств разработки и инструментов можно найти уйму.
Конечно, оптимальным средством для отладки будет специальное программное обеспечение, как например PHP отладчик XDebug. В сети можно найти массу статей на тему установки и работы с XDebug в своей любимой IDE. Вот несколько подобных:
Тем не менее в данной статье мы поговорим о случаях, когда у вас нет возможности установить дополнительное ПО, и вы можете пользоваться только средствами PHP и самого Cotonti. Зачем? — спросите вы... По разным причинам, например по причине, что XDebug это дополнительное расширение PHP и далеко не на каждом хостинге оно установлено или есть возможность его установить. Да и локальный сервер не всегда есть под рукой. Кроме того, существует группа людей, которые привыкли делать все по старинке — руками. Так давайте же облегчим им жизнь за счет встроенных в Cotonti инструментов отладки.
Для использования внутренних инструментов отладки необходимо, либо включить режим отладки в файле конфигурации datas/config.php:
$cfg['debug_mode'] = true;
либо подключить модуль с отладочными функциями самостоятельно:
require_once $cfg['system_dir'].'/debug.php';
Если что-то работает не так, то как правило это связано с тем, что в нашем коде реальные значения при выполнении расходятся с предполагаемыми при проектировании. Самый простой способ проверить значение переменной в определенном месте кода это вывести его на печать (в данном случае на монитор). Однако Cotonti использует буферизацию вывода и обработку шаблонов, что не позволяет на прямую выводить значение в произвольном месте. Если вам будет достаточно вывода значений на пустом экране, то достаточно использовать вывод через функцию cot_print(), для примера.
$qa_abuse = ($usr['id'] == 0 || $row['fp_posterid'] == $usr['id'] ? '' : cot_rc_link(cot_url('plug', 'e=modcp&m=report&post='.$row['fp_id']), $L['qa_report_abuse']; // <DEBUG> cot_print($usr['id'], $row['fp_posterid'], $qa_question); // print these vars // </DEBUG> $qa_best = ($qa_question['q_state'] == QA_QUESTION_OPEN && $usr['id'] == $ft_firstposterid) ? // ...
Вы можете передать не ограниченный список переменных. Вывод функции будет примерно следующим:
Минусом функции cot_print() является то, что она прекращает вывод скрипта в месте вызов и мы не можем отследить дальнейшее изменение значений. Для учета изменений мы можем с помощью Cotonti указать точки наблюдения. Это не позволит отследить непрерывную динамику, но позволит получить лог значений в заданных местах программы.
Перед тем, как использовать cot_watch() или прочие функции, которые пишут в лог файл, вы должны в файле настроек datas/config.php указать путь к каталогу в который он будет записан:
/**
* Путь для сохранения лог файлов.
* Для соблюдения безопасности этот каталог НЕ ДОЛЖЕН быть доступен посторонним лицам (например по HTTP). Защитите log файлы с помощью .htaccess или используйте каталог доступный только по FTP/SSH.
*/
$cfg['debug_logpath'] = '/tmp';
Замечание: имена файлов будут иметь вид `cot_debug_Ymd_His.log`, где Ymd_His
метка даты-времени в соответствующем формате. Поэтому на каждый вызов будет создан свой файл.
Теперь когда вам надо изучить значение переменных, просто вызывайте cot_watch(), указав необходимые переменные в качестве параметров функции:
cot_watch($my_var, $my_array, $obj->id, $arr['item']);
После выполнения скрипта вы можете открыть лог-файл для изучения.
Лог вызовов — это полный список подключаемых файлов и вызываемых функций (с указанием их аргументов) на момент вызова.
Такой лог может быть полезен, например, когда скрипт был завершен с ошибкой (например SQL) и вы не понимаете в каком месте произошла ошибка. Тогда вы включаете режим отладки в datas/config.php :
/**
* Определяет выводить ли отладочную информацию в случае критических ошибок.
* На рабочих сайтах РЕКОМЕНДУЕТСЯ выключить вывод (FALSE).
*/
$cfg['debug_mode'] = TRUE;
Если режим отладки включен и произошла SQL ошибка, вы получите лог стека вызовов, что поможет найти проблемное место в коде:
Возможно вам понадобится получить лог вызовов, тогда просто вызовите cot_backtrace():
cot_backtrace(); // показать стек вызовов
Некоторые функции отладки (типа cot_backtrace() ) используют аргумент $clear_screen , для предотвращения очистки экрана перед выводом. В таком случае вывод будет осуществлен прямо в потоке вашей страницы:
cot_backtrace(FALSE); // не очищать экран
Иногда для полноценного анализа не достаточно отдельных наблюдений и стека вызовов. В таких случаях может помочь дамп переменных и контрольные точки.
cot_vardump();
напечатает всю структуру глобальных переменных и их значений на момент вызова cot_vardump(). Как правило это огромная HTML страница, на которой для поиска необходимой информации лучше использовать текстовый поиск (Ctrl+F).
Если вы отлаживаете функцию и вам интересны только локальные переменные доступные внутри функции, то используйте макрос COT_VARDUMP_LOCALS:
function foo($arg1, $arg2)
{
global $cfg;
$my_var = 'test';
eval(COT_VARDUMP_LOCALS);
}
В результате будет выведены только определенные в функции переменные $arg1, $arg2, $cfg и $my_var.
Возможно вам покажется более удобным запись переменных в лог файл, чем вывод их на экран и прерывание выполнения скрипта. Полноценные отладчики используют механизм точек остановки: вы указываете точки прерывания и запускаете программу пошагово, с остановкой в каждой указанной точке, с возможностью отследить значения переменных. Используя голый PHP, у нас такой возможности нет, поэтому мы используем т.н. «контрольные точки».
Когда встречена контрольная точка, скрипт открывает лог файл и пишет в него где мы находимся и все глобальные и локальные переменные. Вы можете задать несколько контрольных точек для получения более подробной картины происходящего в скрипте.
Давайте на примере реального Плагина для Cotonti посмотрим как использовать этот механизм.
В данном примере я хочу найти проблему со значениями внутри функции, которая синхронизирует уровень пользователя с его счетом. Для этого используем макрос COT_CHECKPOINT_LOCAL:
function qa_sync_scorelvl($user_id = NULL) { global $usr, $qa_levels, $db_users; if (is_null($user_id)) { $user_id = $usr['id']; $urr['score'] = $usr['score']; $urr['scorelvl'] = $usr['scorelvl']; } else { $urr = qa_get_score($user_id); } // <DEBUG> eval(COT_CHECKPOINT_LOCALS); // dump locals // </DEBUG> if (isset($qa_levels[$urr['scorelvl'] + 1]) && $urr['score'] >= $qa_levels[$urr['scorelvl'] + 1]['minscore']) { // ... } // ... return $urr['scorelvl']; }
Далее на страницах сайта выполняем действия, которые приведут к вызову этой функции. Затем открываем лог файла и наблюдаем примерно следующую картину:
/home/trustmaster/htdocs/answers/plugins/answers/inc/points.php, 184: user_id = 2 usr = Array ( [id] => 1 ... ETC. [score] => 4 [scorelvl] => 6 [logpoint] => 1241583533 [isadmin] => 1 [auth_write] => 1 [auth_read] => 1 ) qa_levels = Array ( [0] => Array ( [name] => None [minscore] => -1000 ) [1] => Array ( [name] => One [minscore] => 0 ) [2] => Array ( [name] => Two [minscore] => 50 ) ... ETC. ) db_users = cot_users urr = Array ( [0] => 76 [1] => 2 ) ----------------
Здесь внимание уделено массиву urr, который имеет числовые ключи, в то время, как в функции предполагается использование строковых ключей (ассоциативного массива). Теперь можно исправить недочет и функция заработает как надо.
В следующем примере мне необходимо отладить ту часть плагина, которая выполняется в общей (глобальной) области видимости. Для этого используем функцию cot_checkpoint():
$qa_abuse = ($usr['id'] == 0 || $row['fp_posterid'] == $usr['id'] ? '' : cot_rc_link(cot_url('plug', 'e=modcp&m=report&post='.$row['fp_id']), $L['qa_report_abuse']; // <DEBUG> cot_checkpoint(); // dump globals // </DEBUG> $qa_best = ($qa_question['q_state'] == QA_QUESTION_OPEN && $usr['id'] == $ft_firstposterid) ? // ...
Полученный лог файл достаточно большой т.к. дамп всех перемекнных занимает около 1 Мб (тем не менее надо отметить, что это сильно меньше, чем используют большинство CMS). Поэтому лучше воспользоваться каким-либо редактором для поиска необходимых данных внутри файла:
Конечно данные функции не так удобны как специализированный отладчик (при условии, что вы умеете им пользоваться). Тем не менее они вам могут пригодится, если вы собираетесь писать в вашем скрипте, что-то типа "echo 'Что же здесь не так?'".
И запомните — отладка становится гораздо интереснее, если у вас есть правильное оружие!
Всего: 1, на странице: 1
Поблагодарили: 12 раз