FirePHP – przyjazne debug’owanie aplikacji internetowych

Debugowanie to poważny problem programistów

Bez względu na to jakimi dobrymi programistami jesteśmy nigdy nie ustrzeżemy się błędów. To normalne, błędy popełnia każdy, różnica pomiędzy dobrym programistą a złym polega m. in. na szybkości wykrycia błędnego kodu i naprawienia go.

Mówiąc o błędnym kodzie nie mam na myśli jedynie błędów syntaktycznych, ale również błędów logicznych, które nie powodują widocznych error’ów a jedynie błędne działanie aplikacji. Takie błędy są dużo trudniejsze do wykrycia.

Aby wykryć błędny kod niezbędne jest zdebugowanie zmiennych, obiektów, zasobów, które wykorzystywane są w tworzonej przez nas aplikacji. Brzmi banalnie, jednak w rzeczywistości nie jest to takie łatwe gdyż:

  • po pierwsze trzeba wstawić w odpowiednie miejsca funkcje var_dump() lub print_r()
  • po drugie funkcje te nie wyświetlają przejrzyste i łatwe do zinterpretowania dane
  • po trzecie debug’owanie na ekran może spowodować błędy aplikacji, a debugowanie do pliku jest niewygodne w odczycie (szczególnie w przypadku aplikacji flash’owych lub AJAX’owych)
  • po czwarte zdarza się, że format zwracanych danych uniemożliwia swobodne dodawanie własnych danych do debugowania (np. XML, JSon).
  • po piąge po skończeniu debugowania trzeba usunąć wszystkie instrukcje debugujące

Rozwiązaniem problemu debugowania jest FirePHP

Dużo tych wad… całe szczęście jest na to rozwiązanie. FirePHP to darmowa, open source’owa biblioteka, która wraz z pluginem do Firebug’a idealnie sprawdza się w roli debugera.

FirePHP debuguje dane w konsoli Firebug’a, informacje do debugowania są umieszczone w specjalnych nagłówkach HTTP przez co 'output’ aplikacji pozostaje w nienaruszonym stanie. Rewelacja prawda?

Instalacja firePHP

Wymagania FirePHP to PHP 5.2+, Firefox z pluginem Firebug.

  • Instalujemy plugina do firefox’a Firebug
  • Instalujemy plugina do Firebug’a FirePHP
  • Ściągamy źródła FirePHP, warto zauważyć, że na stronie dostępne są informacje, jak zintegrować bibliotekę z wieloma znanymi frameworkami (CakePHP, CodeIgniter, Drupal, Kohana, ExpressionEngine, PRADO, Symfony, TYPO3, Zend Framework).
  • Integrujemy FirePHP z naszą aplikacją
  • Odpalamy stronę aplikacji w Firefox z uruchomionymi plugin’ami Firebug i FirePHP
  • Klikamy na ikonę Firebug’a a następnie przechodzimy do konsoli. W konsoli powinny być zaprezentowane zdebugowane zmienne naszej aplikacji.
  • W przypadku problemów przydać się mogą: mini tutorial how to, forum dyskusyjne o FirePHP.

Przykład działania

Pod adresem http://blog.adiasz.pl/examples/firephp/ stworzyłem prosty skrypt AJAX’owy łączący się z bazą i wykonujący prościutkie operacje. Jest zintegrowany z FirePHP, zachęcam do testów. Naprawdę warto! (Oczywiście musicie najpierw zainstalować plugin FireBug i FirePHP). Wszystkie pliki wykorzystane w tym przykładzie dostępne są tutaj.

Przykład powinien zaprezentować coś w stylu:

Na koniec, bardzo ważna informacja: po opublikowaniu projektu musicie wyłączyć debugowanie FirePHP poprzez dyrektywę:

$fp = FirePHP::getInstance( true );
$fp->setEnabled ( false );

W przeciwnym razie każdy internauta posiadający zainstalowany ten plugin będzie miał dostęp do niebezpiecznych z punktu bezpieczeństwa danych. Najlepiej w konfigu aplikacji sterować to poprzez zmienną typu boolean $development = true/false. Samych instrukcji debugujących nie trzeba kasować gdyż nie wiadomo kiedy się jeszcze przydadzą.

ps. FirePHP dostępne jest także dla innych niż PHP języków programowania aplikacji webowych: ASP, Python, Ruby.

Przyjemna komunikacja php – flash czyli AMFPHP

Z pewnością każdy programista php, który w swoim projekcie musiał komunikować się z flash’em na własnej skórze doświadczył, że nie jest to zadanie ani przyjemne ani przyjazne w implementacji.

Aby przekazać dane flash’owi, skrypty muszą generować XML’e, które następnie zasysa flash i przetwarza Action Script’em. Bolączek tego rozwiązania jest wiele, poczynając od dodatkowego czasu potrzebnego na implementacje, wygenerowania XML i późniejszego jego zdekodowania a skończywszy na generowaniu sztucznego transferu, ograniczeniach w wielkości plików XML i trudności w debugowaniu.

Znamy zatem bolączki standardowej komunikacji php-flash, zatem trzeba zadać sobie pytanie czy możemy ich uniknąć? Oczywiście!

AMFPHP czyli przyjazna komunikacja na lini php – flash

AMFPHP to open source’owa implementacja Action Message Format (AMF). Bibliteka ta poprzez RPC (Remote Procedure Call) pośredniczy w komunikacji skryptów Action Script ze skryptami serwerowymi, przesyłane dane są serializowane do postaci binarnej. Wymiana danych następuje poprzez plik gateway.php. AMFPHP zachowuje typu danych: obiekt, tablica, wartości typu int, null, bool będą w tej samej postaci dostępne w Action Script w php.

Powyższy opis może nieco odstraszać egzotycznymi nazwami, to tylko teoria w praktyce nie ma się czego obawiać, zaraz na przykładzie pokaże, że instalacja jak i konfiguracja jest banalna.

1. Ściągamy najnowszą wersję AMFPHP, aktualnie jest to wersja 1.9 beta 2. Znaczkiem beta nie ma się co zanadto przejmować, gdyż wersja ta jest stabilna i dobrze przetestowana.
2. Rozpakowywujemy archiwum powyżej document_root gdyż katalog browser i plik gateway.php muszą być dostępne przez HTTP. Resztę plików można by schować poniżej document_root, jednak na potrzeby tej prezentacji nie będę się w takie szczgóły zagłębiać.
3. W katalogu services tworzymy usługi, które maja postac klas PHP. Kod przykładowej usługi:

<?php
require_once( '/my_application/library/core_classes/game.php' );

class FlashGame {

	private $game;
	
	public function __construct() {
		$this->game = new Game();
	}
	
	/**
	 * Metoda zwraca informacje o grze i uzytkowniku
	 *
	 * @param integer - id gry
	 * @param integer - id usera
	 * @return array
	 */
	public function getResults( $gameID, $userID ) {
		$response['info'] = $this->game->getGameInfo( $gameID );
		$response['user'] = $this->game->getUserInfo( $userID );

		return $response;
	}

	/**
	 * Metoda usua uzytkownika
	 *
	 * @param integer - id usera
	 * @return bool
	 */
	public function remove( $userID ) {
		return (bool)$this->game->remove( $userID );
	}
	
	/**
	 * Metoda zwraca obiekt gry
	 *
	 * @return Object
	 */
	public function getGameObject() {
		return $this->game->getGameObject();
	}
}
?>

Klasy usług powinny być maksymalnie proste i jedynie odwoływać się do klas logiki biznesowej aplikacji. Taka konstrukcja zapewnia jasny i przejrzysty kod aplikacji i jest zgodna z kanonami programowania.

Jeżeli poprawnie wykonaliśmy powyższe operacje to będziemy mogli odpalić browsera i z jego poziomu przetestować działanie. Odpalamy browsera (tutaj przykład), przy pierwszym odpaleniu pyta się nas o ścieżkę do gateway i prezentacje wyników, wybierzmy 'tree view’, i klikamy OK.

Po lewej stronie widzimy dostępne usługi, po dwukrotnym kliknięciu na nazwę usługi pojawiają nam się dostępne metody. Domyślnie widoczne są wszystkie metody, można to zmienić pisząc znak podkreślenia na początku jej nazwy. Każda metoda opisana jest komentarzem wyciągniętym z klasy oraz zawiera pola na wprowadzenie testowych danych. Pola te odpowiadają parametrom przyjmowanym przez tą metodę.

Z poziomu browsera możemy przetestować działanie metod poprzez kliknięcie na przycisk call, wyniki prezentowane są w oknie poniżej. Prezentowany wynik jest identyczny z tym co dostaje Flash. Po publikacji aplikacji należy pamiętać o skasowaniu lub zabezpieczeniu hasłem dostępu katalog browsera.

Zatem podsumujmy co daje nam AMFPHP:

  • oszczędność w implementacji
  • łatwe testowanie i debugowanie aplikacji
  • mniejszy transfer serwera
  • większa szybkość działania aplikacji
  • przejrzystość i skalowalność
  • bezpieczeństwo (dane przesyłane binarnie a XML w postaci jawnej)
  • proste wdrożenie do aplikacji

Tutaj do ściągnięcia jest cała paczka AMFPHP wraz z przykładowymi serwisami.