Perl (94) - Catalyst - základy pro psaní aplikace

Perl Napíšeme první catalystovou aplikaci, což bude obnášet vytvoření několika komponent.

14.12.2009 01:00 | Jiří Václavík | přečteno 12861×

Vytvoříme si nyní jednoduchou aplikaci, na které si demonstrujeme základní postupy, které se při vývoji aplikací v Catalystu používají. Nejprve napíšeme aplikaci, která pouze zobrazí text. Na ní bude patrný způsob provázání jednotlivých souborů ve vytvořené adresářové struktuře.

Z teorie již víme, že je třeba vytvořit View, Controller a Model. Naše nová aplikace zatím žádná data potřebovat nebude, takže se zde obejdeme bez Modelu.

Základ aplikace

Na začátku tedy stejně jako minule vytvoříme adresářovou strukturu, která bude základem naší aplikace.

$ catalyst.pl Hello

Vytvoření View

Abychom nyní mohli ovlivňovat výslednou aplikaci, musíme přidat nějaké komponenty. V našem případě bude určitě nezbytný View (to bude výstup pro uživatele, tedy v důsledku jednoduchá stránka) a také Controller, který bude všechno řídit.

Podotkněme pro pořádek, že každý View dědí od Catalyst::View, stejně tak každý Model od Catalyst::Model a každý Controller od Catalyst::Controller.

Vytvořme nyní naši první komponentu. Vytvoříme View s názvem TT. V adresáři script tedy spustíme následující příkaz.

$ perl hello_create.pl view TT TT

Jak již bylo zmíněno, skript hello_create.pl budeme používat k vytváření nových komponent. Při vytváření komponenty je třeba zvolit její typ jako první argument - zde vytváříme komponentu typu View a předáváme tedy argument view. Dalším parametrem je TT, což je jméno komponenty (má vliv na umístění v adresářové struktuře; naše komponenta bude na adrese lib/Hello/View/TT.pm). Poslední argument TT specifikuje, kterým modulem se bude vytvoření View řídit (to jest od kterého modulu bude dědit) - v našem případě jde o Catalyst::View::TT. Zkratka TT zde znamená Template Toolkit. Později si ukážeme i jiné typy View komponent a co to vlastně znamená "řídit se modulem".

Ještě poznamenejme, že místo použití skriptu hello_create.pl bychom mohli přímo vytvořit modul lib/Hello/View/TT.pm, do kterého bychom vložili následující obsah.

package Hello::View::TT;

use strict;
use warnings;
use base "Catalyst::View::TT";

1;

HTML kód

View je tímto hotov. Vytvořme nyní stránku, kterou uživatel ve skutečnosti uvidí. V adresáři root vytvoříme soubor hello.tt, kam vepíšeme (například) HTML kód. Takto může výsledný soubor vypadat.

<html>

<head><title>Toto je první stránka v Catalystu</title></head>

<body>
<h1>Ahoj světe!</h1>
<p>Tady je něco napsáno</p>
</body>

</html>

Zde jsme použili pouze čisté HTML, ale v následujícím dílu se dozvíme, že je to ve skutečnosti šablona, která má HTML teprve vygenerovat.

Vytvoření Controlleru

Nyní je potřeba nějak Catalystu sdělit, co má za jakých podmínek zobrazit. Vytvoříme tedy Controller a uvnitř něj uvedeme Catalystu všechny potřebné informace. Stejně jako posledně využijeme již hotový skript hello_create.pl.

$ perl hello_create.pl controller Hello

Tímto jsme vytvořili v adresáři lib/Hello/Controller náš první Controller s názvem Hello. Otevřeme soubor Hello.pm a podíváme se na jeho strukturu. Budeme ho muset pozměnit. Před editací se ale podíváme, jak vlastně na začátku vypadá.

package Hello::Controller::Hello;

use strict;
use warnings;
use parent "Catalyst::Controller";

=head1 NAME

Hello::Controller::Hello - Catalyst Controller

=head1 DESCRIPTION

Catalyst Controller.

=head1 METHODS

=cut


=head2 index

=cut

sub index :Path :Args(0) {
    my ( $self, $c ) = @_;

    $c->response->body('Matched Hello::Controller::Hello in Hello.');
}


=head1 AUTHOR

Jmeno Prijmeni

Typy akcí v Controlleru

Jak vidíme, je zde obsaženo několik use příkazů, nějaká dokumentace a především podprogram index. K čemu slouží, to se dozvíme později. My ho nyní nebudeme potřebovat a napíšeme si místo něj vlastní.

Na tomto místě je nejdůležitější zodpovědět si otázku, co to vlastně podprogram v Controlleru je. Tedy, odpověď zní, že každý podprogram v Controlleru je akcí, která se vykoná po zavolání jisté URL uživatelem aplikace.

Pojďme si neprve vysvětlit, jaké důsledky má pojmenování tohoto podprogramu a atributy.

Chceme-li, aby se podprogram aplikoval při volání /nejakynazev (to jest http://localhost:3000/nejakynazev), pojmenujeme ho přesně podle toho (tedy bude se v tomto případě jmenovat nejakynazev) a přidáme atribut :Global.

Použijeme-li atribut :Local, výsledná cesta se odvodí od názvu balíčku v Controlleru. Je-li název balíčku například tvaru Hello::Controller::Hello::Zeme::Argentina a podprogram je tvaru

sub info : Local {...}

pak je třeba do prohlížeče zadat adresu http://localhost:3000/zeme/argentina/info.

Dále je možné uvést atribut :Path("cesta/k/necemu"), kterým přímo určujeme cestu. V takovém případě nezáleží na názvu podprogramu. Cestu lze uvést v lokálním nebo globálním kontextu - to Controller pozná podle toho, zda cesta začíná lomítkem.

Taktéž se používají atributy :Regex("regulární_výraz") resp. :LocalRegex("regulární_výraz") pro specifikaci umístění pomocí regulárních výrazů. To je užitečné zejména ve spojení s tím, že lze zachytávat požadované části URL do závorek a získávat je později pomocí pole $c->req->captures. Uveďme příklad. Zadáme-li atribut :Regex("^id(\d+)/typ([ABCD])$"), vyhoví například cesta http://localhost:3000/id954/typB a $c->req->captures->[0] bude obsahovat 954 a $c->req->captures->[1] hodnotu B. Zanedlouho se na objekt $c podíváme hlouběji, a bude tak jasné, co tento zápis vlastně znamená.

Uveďme ještě, že pomocí atributu :Args určujeme, zda mají či nemají být přijaty argumenty. Pokud :Args neuvedeme, chová se Controller benevolentně. Pokud však uvedeme :Args(0), žádné argumenty vzaty nebudou a cesta musí vyhovět přesně - v opačném případě by stránka nebyla nalezena. Zadáme-li :Args(1), vyhoví pouze cesta s argumenty nebo alespoň s koncovým lomítkem.

Existují i další akce. Nyní se však pro zájemce opět odkážeme na dokumentaci, kde jsou navíc všechny atributy vysvětleny na příkladech.

Řešení kolizí

V případě, že více akcí vyhoví zadání URL, má přednost ta nejkonkrétněji určená. To se počítá podle počtu lomítek. Dále platí, že akce určené pomocí regulárních výrazů se zkouší až nakonec. Pokud dle předchozích podmínek nelze rozhodnout, vyhraje ta akce, která je nalezena první. Která to bude, to nemusí být vůbec zřejmé a proto je dobré se sporných případů snažit vyvarovat.

Příklad akce

Pro naše účely si vytvoříme podprogram nazvaný hello s atributem :Global, takže bude výsledná stránka dostupná na URL http://localhost:3000/hello. Podprogram hello tedy bude vypadat takto.

sub hello : Global {
    my ($self, $c) = @_;
    ...
}

$self je objekt Hello::Controller::Hello a nebudeme ho vůbec potřebovat. Pomocí $c budeme celou aplikaci ovládat. Například pomocí něj specifikujeme šablonu pro aktuální stránku, což právě potřebujeme. Pomocí metody stash přiřadíme položce template novou hodnotu. V našem případě vezmeme v adresáři root soubor hello.tt a výsledný podprogram tedy bude vypadat takto.

sub hello : Global {
    my ($self, $c) = @_;
    $c->stash->{template} = "hello.tt";
}

Objekt $c

Na okraj uveďme, že mimo stash lze použít nad objektem $c i několik dalších požadavků. Uveďme je zde však znovu pro přehlednost v jedné tabulce. U každé metody uvádíme i příklad použití. Více informací o tomto objektu lze nalézt v dokumentaci.

PožadavekVýznamPříklady volání
stashpředání dat do View$c->stash->{data} = "nazdar"
resnastavení kódu HTTP statusu$c->res->status(404); $c->res->redirect("http://www.linuxsoft.cz")
reqinformace o požadavku - cookie, uploadované soubory, hlavičky, parametry$c->req->headers->content_type
configkonfigurace$c->config->{root}
logtisk logovacích zpráv$c->log->debug("Knihovna nactena"); $c->log->info("Zbyva 15 sekund")

Speciální akce

Existuje pět speciálních akcí mající svůj vlastní přednastavený význam. Jsou jimi default, begin, end, index a auto.

Metoda default se volá v případě, že zadání URL nevyhoví žádná jiná akce. To je například způsob, jak vytvořit stránku známou jako The page not found. Podobný význam má index, ale ten narozdíl od default nepřijímá argumenty a má přednost.

Výsledná aplikace

Spusťme nyní server. V adresáři script spustíme následující příkaz.

$ perl hello_server.pl

Zkusme do prohlížeče zadat adresu http://localhost:3000/hello.

Naše vlastní stránka

Online verze článku: http://www.linuxsoft.cz/article.php?id_article=1663