Статьи

Радость FirePHP: ускоренный курс

FirePHP — это плагин Firefox и комбинация серверной библиотеки, которая позволяет отправлять в браузер всевозможную полезную информацию из вашего веб-приложения, подобно функции console.log () с JavaScript. В этом обучающем и вспомогательном скринкасте PLUS мы научим вас с самого начала!

Этот учебник включает в себя скринкаст, доступный для пользователей Tuts + Premium.

Так ты думаешь, что ты отличный веб-разработчик? Не читайте дальше, пока не пройдете первый вызов: ответьте (честно) «верно» или «ложно» о себе на следующие утверждения:

  1. Вы используете Firefox для веб-разработки
  2. У вас установлено знаменитое расширение Firebug
  3. Вы разрабатываете на PHP

Если вы ответили на все три с громким «правдой», похлопайте себя по спине. Я прощу вас за то, что вы не получили номер три, но если вы не используете Firefox с Firebug … где вы были?

Вам понадобится эта выигрышная комбинация, чтобы пройти этот урок. Последнее, что вам нужно — стать тем гроссмейстером, убер-разработчиком, убийцей кода своей мечты — это самая важная часть: FirePHP .


FirePHP — это плагин Firefox и комбинация серверной библиотеки, которая позволяет вам отправлять всевозможную сочную информацию из вашего веб-приложения в ваш браузер более приятным способом, чем обычно:

1
echo $variable;

Этот код так распространен. Иногда кажется, что самый быстрый способ просто выделить значение переменной $, чтобы вы знали, что это такое в данный момент выполнения кода.

Но что если переменная $ не является строкой или целым числом? Что если это сложный тип данных, такой как массив или объект? В PHP приведенный выше код не был бы таким полезным:


«Просто используйте print_r ($ variable);» Я слышу, как ты говоришь. Хорошо умные штаны, но это не очень элегантно. Попытка найти значение элемента массива в этом беспорядке — это боль. И это все еще не сортирует объекты!

Когда вы увидите, на что способен FirePHP, вы передумаете! Это превращает отладку в удивительно приятный процесс и приводит к гораздо более переносимому коду.

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


Если у вас не установлено расширение FirePHP, установите его сейчас .

Расширение FirePHP (которое теперь я буду называть FirePHP) полностью зависит от Firebug, поэтому вам это тоже понадобится. Классы на стороне сервера (которые я назову FirePHPCore) доступны как отдельная библиотека . Существует также ряд плагинов для популярных PHP-фреймворков и CMS.

Саймон говорит:

Хотя название предполагает иное, FirePHP не только для разработчиков PHP. Он использует свой собственный набор заголовков HTTP для отправки информации из вашего приложения в браузер, поэтому его можно легко перенести на другие языки. Существуют серверные библиотеки для ASP, Ruby, Python и других. Если нет языка для вашего языка, вы всегда можете бросить вызов себе и написать свой .

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

Загрузите предпочитаемую библиотеку на стороне сервера. В этом уроке я сосредоточусь на использовании автономной базовой библиотеки . Инструкции по настройке других библиотек можно найти в вики FirePHP .

Саймон говорит:

Если у вас есть настройка PEAR и вы предпочитаете ее использовать, просто введите следующие две строки в командной строке:

После распаковки пакета перейдите в папку lib и скопируйте папку FirePHPCore на веб-сервер или в папку приложения.


Саймон говорит:

Одной из замечательных особенностей автономного FirePHPCore является его поддержка PHP4. Так что вы даже можете подключить его к тем ретро-сайтам, которые вы все еще используете


Как и во всех хороших учебниках по кодированию, мы начнем с базового примера, «Hello, World» из FirePHP.

Создайте новый пустой документ PHP. Я назову мой test.php . Сохраните его в корне своего приложения.

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

1
2
3
4
5
<php
ob_start(‘ob_gzhandler’);
  
ob_end_flush();
?>

Конечно, мы не должны забывать включать библиотеку FirePHPCore. Если вы работаете на PHP5, добавьте это в начало файла:

1
include_once (‘includes/FirePHPCore/fb.php’);

Если вы используете PHP4, вместо этого включите файл fb.php4 .

Саймон говорит:

Нам не нужно включать файл класса, так как он включен в файл fb.php.

Теперь мы можем начать вывод на консоль Firebug. Введите следующее после ob_start () и перед ob_end_flush () :

1
FB::info(‘Hello, FirePHP’);

Саймон говорит:

FirePHPCore имеет процедурный и объектно-ориентированный API. Там действительно нет никакой разницы между ними, и вы можете использовать то, что вы предпочитаете.

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

Откройте Firefox, запустите Firebug и перейдите на эту страницу. Вы должны получить что-то вроде этого:


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


Давайте посмотрим, что происходит, когда мы передаем комплексную переменную. Мы построим массив и посмотрим, что мы получим. Добавьте следующий код сразу после последнего вызова FB :: info ():

1
2
3
4
5
6
7
$array[‘key1’] = ‘some content’;
$array[‘anotherKey’][] = 1234;
$array[‘anotherKey’][] = 5678;
$array[‘anotherKey’][] = 9012;
$array[] = null;
  
FB::info($array, ‘My Array Test’);

Теперь сохраните, зайдите в Firefox и обновите.


Хорошо, выглядит хорошо … но, подожди, где все выходные? Наведите курсор на эту новую строку.


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

С объектами становится еще интереснее! FirePHPCore полностью использует рефлексию для проверки свойств объекта — даже приватных.

Саймон говорит:

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

Вы можете узнать больше об API FirePHPCore в Штаб-квартире FirePHP .


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

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

Что-то вроде этого сделало бы это:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<php
ob_start(‘ob_gzhandler’);
$requestStart = microtime();
  
/**
 * Application runs code, includes, functions and all that…
 */
  
$requestEnd = microtime();
  
// Calculate the time taken
$executionTime = $requestEnd — $requestStart;
  
FB::info($executionTime, ‘This request took (seconds)’);
  
ob_end_flush();
?>

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

Саймон говорит:

Вы можете использовать расширение YSlow для Firebug, чтобы отслеживать общее время загрузки страницы и скорость отклика приложения.

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

Вы также можете записать сами запросы SQL. На самом деле, вы можете объединить эти два бита данных. И разве не было бы неплохо отобразить это в хорошо структурированной таблице?

Ну, у Firebug есть структура таблиц, и у FirePHPCore есть обертка для этого:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<php
// This assumes you’ve already included the fb.php file
  
/**
 * File: myDb.class.php
 * You would instantiate this class to run queries
 */
class myDb extends mysqli {
    public static $queries;
    public static $totalQueryTime;
      
    public function query ( $query ) {
        // Start query timer
        $startTime = microtime();
          
        $result = parent::query ( $query );
          
        // End query timer
        $endTime = microtime();
  
        $execTime = $endTime — $startTime;
  
        // Increment the total query time
        self::$totalQueryTime += $execTime;
  
        if ( $result ) {
            // Notice that for each query we record the query string itself and the time it took to execute
            self::$queries[] = array ( $query, $execTime );
        }
        else {
            FB::error ( $query, ‘Error in Query: ‘ . mysqli_error ( $this ) );
            FB::trace ( ‘Stack Trace’ );
        }
  
        return $result;
    }
}
  
  
/**
 * File: debug.php
 * Include this file at the very end of your application
 */
if ( is_array ( DB::$queries ) ) {
    $header = array(‘SQL Query’, ‘Execution Time (s)’);
          
    $footer = array(‘Total Execution Time:’, DB::$totalQueryTime);
          
    $table = array_merge($header, DB::$queries, $footer);
}
  
FB::table( count(DB::$queries) . ‘ SQL queries executed’, $table);
?>

Саймон говорит:

Я добавил пару дополнений сюда. В файле myDb.class.php, если переменная $ result возвращает false , это означает, что этот запрос не выполнен. Поэтому я использую FB :: error (), чтобы пометить это как ошибку в Firebug и показать мне запрос, а также FB :: trace (), чтобы показать мне стек процессов, приводящий к некорректному запросу.

Ключевым моментом здесь является метод FB :: table () . Это упрощает создание структурированной отладочной информации.

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


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

Использование FirePHPCore для запросов AJAX ничем не отличается от его использования для синхронных запросов. Просто используйте функции, как обычно. Когда ваше приложение делает запросы AJAX, дополнительная информация заголовка FirePHP поступает, и клиентское расширение обрабатывает ее в консоли Firebug. Давай попробуем.

Создайте новый файл с именем ajax.php в корне вашего приложения. Поместите туда следующий код:

01
02
03
04
05
06
07
08
09
10
<php
include_once(‘includes/FirePHPCore/fb.php’);
ob_start(‘ob_gzhandler’);
  
FB::info($_GET[‘str’], ‘My AJAX Test’);
  
echo ‘My clean AJAX response’;
  
ob_end_flush();
?>

Теперь в вашем файле test.php добавьте следующее после вашего последнего вызова FB :: info ():

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
?>
  
<script src=»http://www.google.com/jsapi»></script>
  
<script type=»text/javascript»>
    google.load(‘jquery’, ‘1.3’);
</script>
  
<script type=»text/javascript»>
    $(document).ready(function(){
        $(‘#button’).click(function(){
            // Notice the GET parameter we’re passing.
            $(‘#ajaxContainer’).load(‘ajax.php?str=I+love+jQuery’);
        });
    });
</script>
  
<input type=»button» value=»Click Me!»
<div id=»ajaxContainer»></div>
  
<php

Обновление test.php в Firefox должно показать вам «Click Me!» кнопка. Когда вы щелкаете по нему, браузер должен выполнить AJAX-запрос и загрузить ответ (в данном случае обычный текст) в <div id = «ajaxContainer»>.


Что еще более важно, FirePHP добавляет новый узел в Firebug, который показывает нам любые сообщения FirePHP, которые мы зарегистрировали в файле ajax.php.

Придерживайтесь этого в начале своего приложения, и даже старые неприятные ошибки PHP будут сброшены в Firebug!

1
2
3
4
5
6
7
8
set_error_handler(‘myErrorHandler’);
  
// You could add optional parameters $errfile, $errline and $errcontext for more detail
function myErrorHandler($errno, $errstr) {
    FB::error($errstr, ‘Error number’ . $errno);
}
  
// Continue with normal execution

Это гораздо более чистый и безопасный способ сообщения об ошибках. Будет еще лучше, если вы продемонстрируете свои приложения клиентам во время их разработки (и риску возникновения некритических ошибок) — если они не используют Firefox, с Firebug и FirePHP, они не увидят эти ужасные ошибки , но вы будете … в Firebug. Больше не нужно менять уровни сообщений об ошибках, чтобы сохранить порядок! Теперь это более быстрое развитие.


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

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

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

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

Если вам абсолютно необходимо включить FirePHP на рабочих сайтах, например, для удаленной отладки, убедитесь, что он включен, и не забудьте выключить его, когда закончите. Что-то вроде:

1
2
3
4
5
6
define(‘DEBUG_MODE’, true);
FB::setEnabled(false);
  
if ( DEBUG && $_SESSION[‘userIsAdmin’] ) {
    FB::setEnabled(true);
}

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


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

Что еще более важно, это спасло мою кожу более чем в несколько раз. Я был в состоянии отлаживать сайты в производстве без необходимости их отключения. Это сделало отладку AJAX очень реальной возможностью, и, поскольку она с открытым исходным кодом и бесплатна в использовании, стоимость внедрения чрезвычайно низка.

Добавьте к этому тот факт, что мои приложения стали более переносимыми, у меня есть лучшее представление о них, и я узнал несколько новых трюков по пути, что не нравится?

Все больше и больше веб-разработчиков используют браузер в качестве основного инструмента разработки. И почему бы нет? Это где наши приложения предназначены для работы. Так что кажется более естественным поместить профилирование и отладку прямо в браузере; где мы проводим большую часть нашего времени в любом случае отладки!

Думаешь, пришло время прекратить использовать эхо сейчас? Поздравляю, Супер-Дев!


FirePHP был создан Кристофом Дорном . Версия 0.3.1 является текущей стабильной версией. Версия 1.0 находится в разработке и обещает некоторые захватывающие новые функции.