В качестве технического менеджера пакета программных проектов одной из моих обязанностей является проверка кода. Одна из вещей, которые я вижу гораздо чаще, чем хотелось бы, когда делаю обзоры, — это отладка зафиксированного кода PHP и продвижение по цепочке. Поднимите руку, если вы сделали это:
<?php $total = $someService->getComplexTotal(); var_dump($total); $someOtherService->processTotal($total);
Итак, вам не нужно поднимать руку. Но скорее всего, вы немного улыбнулись. Либо «Да, как он узнал, что я это делаю?», Либо «Да, я раньше это делал. Но теперь у меня есть другие способы отладки ». Какая потрясающая игра!
Мы должны использовать метод отладки, который не отображает информацию для непрограммистов через веб-страницу. То есть мы никогда не должны видеть дампы переменных или операторы SQL, выводимые на экран. Этого не может быть
Самый безопасный метод отладки требует настройки вашей IDE для использования таких инструментов, как Xdebug или Zend Debugger, для отслеживания выполняемого в данный момент кода. Это не всегда практично. В отсутствие использования полностью настроенной среды отладки я перехожу к FirePHP.
Используйте FirePHP для безопасной отладки PHP
FirePHP — это PHP-библиотека, используемая для генерации консольных сообщений в браузере из вашего PHP-кода. Консольные сообщения обычно создаются с помощью JavaScript, но FirePHP отправляет подобные сообщения в виде заголовков HTTP с ответом от сервера. Различные расширения браузера выступают в качестве прокси для методов консоли JavaScript и преобразуют эти заголовки в сообщения журнала консоли.
Почему это «безопаснее» вывода отладочных данных? Что ж, при использовании таких методов, как console.log()
JavaScript, вам необходимо предпринять согласованные усилия для просмотра отладочных сообщений. Обычные посетители не будут открывать консоль разработки в своем браузере и, следовательно, не будут видеть ваши сообщения отладки. Если вы вместо этого var_dump()
, то нет способа НЕ видеть сообщения.
Обратите внимание, я называю это «безопаснее», но вы все равно должны позаботиться о том, чтобы не оставлять звонки FirePHP включенными с критической системной информацией, доступной в производстве.
Настройка FirePHP
Посетите страницу установки ядра FirePHP, чтобы выбрать загрузку библиотеки напрямую или получить команды для установки через PEAR. Если вы используете другие платформы, такие как Zend Framework, для FirePHP уже существуют средства записи журналов, поэтому дополнительная загрузка не требуется.
Если вы используете Firefox, установите FireBug для расширенного набора инструментов для отладки ваших веб-приложений, а затем установите расширение FirePHP для расширения FireBug и перехвата сообщений FirePHP.
Если вы используете Chrome, просто установите одно расширение FirePHP4Chrome . (Полное раскрытие: я создал это расширение Chrome и активно развивал его. Мне не очень повезло с другими плагинами в Chrome.)
Наконец, откройте консоль в своем браузере. В Firefox щелкните значок Firebug, чтобы отобразить консоль. Убедитесь, что FirePHP включен, щелкнув значок FirePHP в представлении консоли и отметив, установлен ли флажок рядом с включенным. В Chrome щелкните значок настроек, выберите инструменты и нажмите «Инструменты разработчика», чтобы открыть консоль. FirePHP4Chrome будет автоматически включен при открытии консоли.
Базовая регистрация с FirePHP
Если вы когда-либо работали с ведением журналов с разными уровнями ошибок, вы, несомненно, видели дебаты о различиях между типами ошибок: «предупреждение» и «ошибка». Или следует ли использовать «информацию» и «журнал»? . »Хотя у меня есть свои собственные мнения, я не буду утомлять вас ими. Достаточно сказать, что могут быть причины отличать сообщение, которое вы хотите отправить на консоль, отличным от стандартного сообщения.
В настоящее время протокол FirePHP поддерживает четыре типа сообщений: журнал, информация, предупреждение и ошибка. Я хочу показать вам, как вы можете использовать каждый из них. Это зависит от вас, чтобы выбрать правильный для вашей среды и контекста отладки / ведения журнала.
Следующий код демонстрирует, как включить библиотеку FirePHP и выполнить каждый из типов журналирования.
<?php require 'FirePHPCore/fb.php'; FB::log('Log message'); FB::info('Info message'); FB::warn('Warn message'); FB::error('Error message');
Приведенный выше код просто включает базовую библиотеку FirePHP и вызывает различные методы ведения журнала. Есть несколько способов вызвать методы библиотеки; он поддерживает чисто глобальные процедурные вызовы функций, статические вызовы методов и вызовы полностью объектных объектов. Я использую статические методы, потому что обычно я хочу использовать FirePHP только в одной строке для отправки отладочной информации; Я хочу сделать это быстро!
Ниже вы увидите скриншоты с выводом на Firefox и Chrome.
Дисплей Firefox немного красивее. В версии Chrome отсутствует значок «информация», поскольку console.log()
в Chrome пока не поддерживает значок. Позже вы также заметите, что вывод таблицы в Chrome очень элементарен. Это связано с тем, что Chrome еще не поддерживает console.table()
в console.table()
наборе функций. Хотя я использую Chrome для собственной разработки, я буду использовать Firefox на своих скриншотах в оставшейся части этой статьи.
Чтобы сделать регистрационную информацию более полезной, можно добавить метку к сообщениям журнала. Это указывается в качестве второго параметра методов ведения журнала.
<?php require 'FirePHPCore/fb.php'; $turtles = $zooService->fetchAllTurtles(); FB::info($turtles, "All Turtles");
Как вы видите на следующем скриншоте, сервис зоопарка в моем примере принес три черепахи. Было ясно, что это конкретное сообщение журнала было черепахами, и, скажем, не известных актеров или что-то еще. Чтобы сэкономить место, Firebug / FirePHP свернул вывод. Наведите курсор на строку, чтобы увидеть весь вывод.
Расширенная регистрация с FirePHP
FirePHP отлично подходит для генерации одноразовых сообщений журнала, как я уже продемонстрировал. Тем не менее, есть более продвинутые функции, которые делают FirePHP действительно блестящим. Три, о которых я расскажу быстро, — это группировка сообщений, таблицы и трассировки.
Группировка
Давайте представим, что у нас есть небольшой журнал, который мы должны сделать в цикле. Это может потенциально выйти из-под контроля и вызвать прокрутку консоли. Мы можем захотеть поместить это в группу, чтобы ее можно было легко свернуть и расширить. В этом примере кода я зарегистрирую четыре записи информации, которую я хочу сгруппировать вместе.
<?php require 'FirePHPCore/fb.php'; $specialHashes = array(); for ($x = 0; $x < 5; $x++) { $specialHashes[$x] = sha1($x . 'somesalt'); FB::info($specialHashes[$x], "Hash #" . $x); }
И вывод:
Сообщение в журнале немного длиннее, чем хотелось бы. Я хочу, чтобы это было разумно сгруппировано, и чтобы это было свернуто. Я изменил код, чтобы включить методы группировки, встроенные в FirePHP.
<?php require 'FirePHPCore/fb.php'; $specialHashes = array(); FB::group('Special Hashes'); for ($x = 0; $x < 5; $x++) { $specialHashes[$x] = sha1($x . 'somesalt'); FB::info($specialHashes[$x], "Hash #" . $x); } FB::groupEnd();
А теперь новый вывод:
Как видите, теперь есть возможность минимизировать группу, помеченную «Специальные хеши». FirePHP даже позволяет свернуть группу по умолчанию. Просто замените вызов group()
и добавьте массив параметров следующим образом:
FB::group('Special Hashes', array('Collapsed'=>true));
таблицы
FirePHP может отправлять табличные данные довольно легко. На самом деле, поскольку метод console.table()
Firefox очень console.table()
, данные отображаются прекрасно и их легко понять. (О, Chrome, пожалуйста, подтянись!) Для отправки данных таблицы в FirePHP используется массив столбцов. Однако первым элементом массива должны быть имена столбцов. Используя наш специальный пример хэшей, давайте запишем их в виде таблицы:
<?php require 'FirePHPCore/fb.php'; $specialHashes = array(); for ($x = 0; $x < 5; $x++) { $specialHashes[] = array($x, sha1($x . 'somesalt')); } $headers = array('Hash #', 'Hash Value'); $logTable = array($headers) + $specialHashes; FB::table("Special Hashes", $logTable);
Вы можете заметить одну вещь, которую я сделал немного по-другому — создание переменной $logTable
. Поскольку первый элемент массива, отправляемый методу table (), должен быть меткой столбца, я создал временную переменную, чтобы выполнить эту задачу для меня. Я не хочу манипулировать массивом $specialHashes
— это мои бизнес-данные. Метод table()
принимает параметр Label, за которым следует массив столбцов.
Когда консоль загружает данные из FirePHP, таблица свернута. Для приведенного выше снимка экрана я щелкнул ярлык, чтобы отобразить данные.
Следы
Следы могут быть неоценимы при отладке кода PHP. Если вы хотите связать их с сообщением журнала, показывающим значение переменной в определенной точке кода, или вам нужна дополнительная информация из исключения, трассировка находится там, где она есть. Очень просто, вы можете вызвать трассировку в любом месте вашего PHP-кода с помощью FirePHP, как показано здесь:
<?php require 'FirePHPCore/fb.php'; FB::trace('Simple Trace');
И вывод:
Когда вывод был отображен, я просто нажал на метку «Простой след», чтобы отобразить весь след. Этот пример очень прост и показывает, как легко его можно вставить в любой код.
Давайте сделаем пример немного более сложным (хотя, я сомневаюсь, что вы действительно захотите сделать такой код в своем проекте):
<?php require 'FirePHPCore/fb.php'; function one() { echo "This is one.<br>"; two(); } function two() { echo "This is two!<br>"; FB::trace('Trace from function two.'); } one();
Здесь вызывается функция one()
. Функция two()
вызывается в последней строке функции. После того, как two()
завершается, он выполняет вызов трассировки для FirePHP. Следующий снимок экрана показывает вывод Firefox:
… И это еще не все!
С помощью FirePHP вы можете сделать гораздо больше, чем приведенные выше примеры. Чтобы просмотреть дополнительную информацию об указании других параметров, настройке трассировок исключений и даже об использовании утверждений, посетите штаб-квартиру FirePHP .
Бонусный пример
Как и в большинстве статей, посвященных стилю введения, информация здесь была относительно общей, а примеры — умеренными. Нужен более подробный пример, чтобы убедить вас использовать FirePHP? Пошли:
<?php try { $key = "user.{$userId}"; if (!SimpleCache::has($key)) { FB::info($key, 'Cache miss:'); $userService = new UserService(); $user = $userService->fetchById($userId); SimpleCache::set($key, $user); } $user = SimpleCache::get($key); } catch (Exception $e) { FB::error($e); Router::generate500(); }
Этот простой пример кода построен для извлечения пользовательского объекта. Эта система использует некоторый тип кэширования и генерирует исключения, когда пользователь недоступен. При первом запуске этого кода пользователь не кэшируется, поэтому FirePHP отправляет информационное сообщение. Для идентификатора пользователя 5 следующий снимок экрана показывает вывод.
При втором запуске кода метод info()
не вызывается, и сообщение не отправляется на консоль. Теперь давайте представим, что кеш стал недоступен. (Я мог бы создать код, чтобы он мог работать, если бы кеша не было, но это просто лишило бы всех удовольствия!) В случае, когда кеш больше не доступен, метод set()
будет выбрасывать исключение. На экране появится сообщение об ошибке 500, согласно этому коду. Но я хотел бы видеть исключение и сразу отслеживать трассировку. Вот где появляется метод error()
. Он может интерпретировать объект Exception
и хорошо его регистрировать.
Резюме
Самый безопасный способ отладки вашего PHP-кода — использовать среду отладчика, настроенную в вашей IDE. Однако для более быстрой отладки, а также ведения журнала на уровне приложений FirePHP может сыграть важную роль.
Изображение через Fotolia