V minulém dílu seriálu o Nette Framework jsme vytvořili jednoduchý našeptávač jako ukázku komunikace mezi serverem a prohlížečem, tedy mezi PHP a JavaScriptem. K tomuto příkladu se nyní vrátíme, abychom si ukázali, jak AJAXové aplikace ladit. Takže si jej stáhněte a spusťte. A udělejte v něm chybu!
Ladění AJAXových aplikací
Jakou chybu? Například na řádku class AutoCompletePresenter extends Presenter
změňte název třídy Presenter
za Prasenter
. Po zobrazení v prohlížeči se objeví už známá tvář Laděnky (třída NetteDebug), kterou jsme si představili už dříve.

Pozn.: Nette Framework se neustále zdokonaluje a fatální chyby PHP se naučila Laděnka zachytávat teprve nedávno. Pokud tuto obrazovku nevidíte, ujistěte se, že používáte aktuální verzi.
NetteDebug
velice přehledně zobrazil chybu a programátorovi stačí letmý pohled, aby zjistil, která bije, a mohl chybu okamžitě opravit. To vám samozřejmě neříkám nic nového. Jenže s AJAXovými aplikacemi se pojí jedna poměrně nepříjemná záležitost. Komunikace se serverem probíhá „neviditelně“.
Takže pokud k chybě dojde během AJAXového požadavku, může být odpověď serveru neúplná, poškozená nebo prostě žádná. Může také chybu signalizovat HTTP kódem 500. Ale ať už nastane jakákoliv varianta, z pohledu uživatele prohlížeče se obvykle projeví tak, že se nic nestane. AJAX přestane AJAXovat. Nanejvýš dojde k chybě JavaScriptu.
Což je chvíle, kdy Běžný Programátor™ nastoupí dlouhé a strastiplné pátrání po původu té nedobroty. Do PHP kódu připíše několik dumpů, JavaScript obohatí o pár příkazů alert()
. Profesionál používající IDE se pustí do krokování kódu. No a Nette Programátor™, prostě koukne a vidí:

Laděnka se postarala o to, aby se chyba či výjimka vypsala do konzole Firebugu. Vyzkoušejte si to. Jako prohlížeč si otevřete Firefox a pokud je ještě nemáte, stáhněte si do něj pluginy
Aktivaci FirePHP provedete tak, že otevřete okno Firebugu a povolíte panel Síť (Net). Spusťte prográmek Našeptávač a než začnete psát do textového pole, vytvořte v kódu chybu, za kterou vás interpretr PHP nepochválí. Pak stačí do políčka něco napsat a „nepochvala“ se s výstižným popisem zobrazí v konzoli. Včetně jména souboru a čísla řádku, kde se chyba nachází.
Dovedete si představit pohodlnější způsob ladění AJAXových aplikací?
Budu se opakovat když řeknu, že problematika AJAXu je mnohem zajímavější a rozmanitější, než co jsme si stihli dosud ukázat. Už jí byl dopřán prostor o délce 2 ½ dílu a celá řada dalších témat nervózně postává za dveřmi a čeká na svou chvíli. Opusťme tedy AJAX a zájemce o další návody a tipy bych rád odkázal na bezplatné neformální setkání Poslední sobota, kde jim bude v programu věnován prostor.
Objektivní rest
Už na začátku seriálu jsem zmiňoval třídu NetteObject
, prapředka všech tříd v Nette Framework. Díky ní se objekty staly striktnější, tj. při použití nedeklarované proměnné reagovaly vyhozením výjimky. Zároveň jsem zmínil, že to není jediná schopnost této třídy a že další si nechám na příště. A příště je právě dnes.
NetteObject
doplňuje do jazyka PHP tzv. syntactic sugar, tedy cukřík, který má osladit život programátorův.
Properties
Pojmem property (česky vlastnost) se v moderních objektově orientovaných jazycích označují speciální členy tříd, které se tváří jako proměnné, ale ve skutečnosti jsou reprezentovány metodami. Při přiřazení nebo čtení hodnoty této „proměnné“ se zavolá příslušná metoda (tzv. getter a setter). Jde o velice šikovnou věc, díky ní máte přístup k proměnným plně pod kontrolou. Bohužel ale v PHP nejsou implementované.
Pomocnou ruku natahuje NetteObject
. Každá třída, která je jeho potomkem, umí property imitovat.
require 'Nette/loader.php';
// pokud používáte verzi pro PHP 5.3, odkomentujte následující řádek:
// use NetteObject;
class Circle extends Object
{
private $radius;
public function getRadius()
{
return $this->radius;
}
public function setRadius($radius)
{
$this->radius = max(0, (float) $radius); // ošetření vstupu
}
public function getArea()
{
return M_PI * $this->radius * $this->radius;
}
}
$circle = new Circle;
// klasický způsob pomocí volání metod
$circle->setRadius(10); // nastav poloměr kruhu
echo $circle->getArea(); // vypiš obsah kruhu
// ekvivalentní řešení s využítím properties
$circle->radius = 10; // mapuje se na volání setRadius()
echo $circle->area; // mapuje se na volání getArea()
Gettery i settery musí být veřejné metody. Nette zároveň kontroluje velká a malá písmena, takže přiřazení do proměnné $circle->rAdIuS
by vedlo k vyhození výjimky neexistující proměnná. V případě property area
existuje pouze getter (tj. metoda getArea()
), takže jde o property pouze ke čtení. Příkaz $circle->area = 123;
by opět vyvolal výjimku.
S properties jsme se v průběhu seriálu setkávali docela často, aniž byste si toho nejspíš všimli. Šlo třeba o přístup k $presenter->template
nebo $presenter->payload
. Ve skutečnosti jde o properties, které jsou navíc pouze pro čtení. Presenter je implementuje metodami $presenter->getTemplate()
a $presenter->getPayload()
. Schválně si můžete vyzkoušet, že volání $presenter->template = NULL
nebude úspěšné.
Extension method
Novinkou třetí verze C# jsou extension method, které umožňují přidat nové metody do již existující třídy (nikoliv přepsat). K čemu je to dobré? Třeba kdybychom chtěli čistým způsobem začlenit do třídy Circle
metodu vracející obvod kruhu, ale neměli bychom možnost editovat zdrojový kód.
Samozřejmě je možné takovou metodu definovat mimo třídu, třeba takto:
function getCircleCircumference(Circle $circle)
{
return $circle->radius * 2 * M_PI;
}
$circle = new Circle;
$circle->setRadius(10);
echo getCircleCircumference($circle); // vypíše obvod kruhu
Ale tohle není moc sexy. Hezčí by bylo mít metodu getCircumference()
přímo ve třídě Circle
. To lze! Stačí říct Nette, aby ji vytvořil a namapoval na funkci getCircleCircumference
.
// pro PHP 5.3
Circle::extensionMethod('getCircumference', 'getCircleCircumference');
// kvůli technickým omezením je třeba v PHP 5.2 zapsat příkaz takto:
Circle::extensionMethod('Circle::getCircumference', 'getCircleCircumference');
// a ejhle:
echo $circle->getCircumference(); // funguje!
Rozšiřující metody neporušují princip zapouzdření, protože mají přístup pouze k veřejným členům tříd. Mohou být také napojeny na rozhraní (interfaces), takže v každé třídě, která dané rozhraní implementuje, bude metoda k dispozici. A lze jim také předávat parametry.
Reflexe
Drobností je i podpora sebereflexe:
$circle = new Circle;
echo $circle->getClass(); // vrací název třídy, tedy Circle
$reflection = $circle->getReflection(); // vrací objekt ReflectionObject
// příklad použití: má třída Circle metodu test?
$has = $circle->getReflection()->hasMethod('test');
Pokračování příště
A co příště? Podíváme se, jak Nette Framework zjednodušší práci se sessions a jak řeší s tím spojená bezpečnostní rizika.
Autor článku je vývojář na volné noze, specializuje se na návrh a programování moderních webových aplikací. Vyvíjí open-source knihovny Texy, dibi a Nette Framework a pravidelně pořádá školení pro tvůrce webových aplikací, které od podzimu 2009 nabídne kurz vývoje AJAXových aplikací.
Přehled komentářů