Nette Framework - přednáška na ZČU pro KIV/WEB

Post on 07-Jul-2015

1,163 views 2 download

description

Poslední přednáška z předmětu KIV/WEB na ZČU určená pro studenty začínající v oboru webových aplikací.

transcript

NETTEFRAMEWORK

since 2004 by David Grudl

2.1-dev

nette.org

Martin Zlámal

Co se dnes dozvíte?

1. Co je to vlastně ten framework

2. Co je to MVP

3. Něco málo o šablonách

4. Něco málo o prezentační vrstvě

5. Něco málo o modelové vrstvě

6. Jak na AJAX / AJAJ

7. Praktická ukázka (pokud zbyde čas)

Kdo se bez Nette neobejde?

Bandzone.cz, Blueboard.cz, ČSFD, eshop.iaeste.cz, E15.cz,

FRESH-hosting.cz, H1.cz, Primat.cz ROOT.cz,

Mladá fronta, Slevomat, ujop.cuni.cz, Uloz.to, Václav

Klaus, můj blog a mnoho dalších…

Co je to ten framework?

cool URL AJAX / AJAJ

Dependency Injection

SEO

DRYKISS

MVC

Web 2.0

Context-Aware Escaping

Tak co je to tedy ten

framework?

Je to nástroj…

„Framework je jako lopatička na pískovišti. Hrad z písku postavíte i

rukama, ale lopatička je prostě lepší.“

Co naopak není framework

Není to WordPress…

„Framework není instantní hrad z písku. Je zapotřebí trošku snahy,

ale s lopatičkou to jde skoro samo.“

MODEL - VIEW - PRESENTER

Model je rozsáhlá vrstva aplikace. Zajišťuje aplikační logiku.

Není to pouze hloupá obálka pro databázové dotazy!

View zobrazuje data z modelu.

Presenter to celé řídí.

Je to nutné? Není, ale dává to smysl.

VIEWTen, co se rád ukazuje…

Proč vlastně používat šablony?

• Spojení HTML a PHP nikdy nevypadalo dobře.

• A nejde jen o to, jak je to „hnusné“. Není to ani bezpečné.

• Máte jistotu v tom, jak escapovat HTML, XML, CSS, JS, nebo REGEX?

• Oproti tomu šablony jsou bezpečné a přehledné.

• A navíc šablonováním neztrácíte výkon, takže co vlastně řešíme?

• Protiargumenty?

"); alert(1); //XSS ;-)

• Stačí najít jedno opomenuté neošetřené místo. (optional)

• Pokud do neošetřeného místa protlačíme alert(1); protačíme už vše...

• Nyní již snadno získáme například administrátorské session ID.

• Session ID můžeme snadno podstrčit a vydávat se tak za administrátora.

• Změníme admin hesla, získáme citlivé údaje, zveřejníme citlivé údaje, smažeme

databáze, smažeme celý web, přečteme si emaily, smažeme emaily...

• To vše jen kvůli zapomenutému htmlspecialchars. Creepy…

<?php if ($items): ?><?php $counter = 1 ?><ul><?php foreach ($items as $item): ?>

<li id="item-<?php echo $counter++ ?>"><?php echo htmlSpecialChars(mb_convert_case($item, MB_CASE_TITLE)) ?>

</li><?php endforeach ?></ul>

<?php endif?>

<ul n:if="$items">{foreach $items as $item}

<li id="item-{$iterator->counter}">{$item|capitalize}</li>{/foreach}

</ul>

Jaký kód je „lepší“?

Cappuccino? Latte!

Makra{$variable} vs. {!$variable}{if $cond} … {elseif $cond} … {else} … {/if}{ifset $var} … {elseifset $var} … {/ifset}{ifCurrent $link} … {/ifCurrent}{$cond ? $value1 : $value2} popř. {$cond ? $value}{foreach $arr as $item} … {/foreach}{for expr; expr; expr} … {/for}{sep} … {/sep}{snippet name} … {/snippet}{dump $variable} popř. {dump}

Context-Aware EscapingJméno: {$name} {$surname}<br>Věk: {date('Y') - $birth}<br>

<script type="text/javascript">var pole = {$arr};var name = {$name}; // pozor, zapisuje se bez uvozovek!

</script>

Jméno: &lt;script&gt;John Doe&lt;/script&gt;<br>Věk: 23<br> //… následuje <script type=…

var pole = [1,2,3];var name = "<script>John";

Linky a podmínky<a href="{link edit, 10}">edituj</a><ul class="menu">

<li><a href="{link Default:default}">...</a></li><li><a href="{link}">...</a></li>... <li {ifCurrent Default:default}class="current"{/ifCurrent}>

<a href="{link Default:default}">...</a></li><li {ifCurrent Default:*}class="current"{/ifCurrent}>

<a n:href="Default:default">...</a></li>

</ul>

Cykly a podmínky

{foreach $rows as $row}{if $iterator->first}<table>{/if}

<tr id="row-{$iterator->counter}"><td>{$row->name}</td><td>{$row->email}</td>

</tr>// vzpomínáte na {sep}, {/sep} ?{if $iterator->last}</table>{/if}

{/foreach}

N:makra

Běžné zadání (menu webu):

Vypište data z databáze jako elementy <li>, neznáte dopředu jejich počet a

chceme, aby každý lichý řádek měl třídu alt a poslední třídu last. Pokud by byl

poslední řádek lichý, má mít obě třídy. A protože jsme puntičkáři, nechceme

v kódu žádné prázdné <li class=" "> apod. V <li> elementu bude odkaz,

který bude mít třídu current, pokud je odkaz právě aktivní.

Řešení:

<ul>{foreach $data as $item}<li n:class="$iterator->odd ? alt, $iterator->last ? last">

<a href="#" n:class="$presenter->isLinkCurrent('Presenter:*') ? current">{$item}

</a></li>{/foreach}

</ul>

Helpery<h1>{$heading|upper}</h1>

{var $title = 'Řekněte, jak se máte?'}{$title|truncate:20} Řekněte, jak se…

{var $name = 'náš produkt'}{$name|webalize} nas-produkt

<img src="{$img|dataStream}"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">

Shrnutí šablon

• Není důvod je nepoužívat, protože…

• Zvyšují čitelnost a přehlednost výsledného kódu.

• Ulehčují práci a nesnižují výkon aplikace.

• Umožňují aplikaci lépe zabezpečit.

• Existují makra, n:makra a helpery…

Nějaké dotazy k šablonám nebo k tomu, co jsem doposud říkal?

MODELTen, co dělá chytrého…

Nette\Diagnostics\Debugger

„Tracy“

„Není to pouze obálka pro databázové

dotazy!“

No vlastně je…

Nette\Database• Každý nechť používá, co se mu zlíbí, ale když mluvíme o Nette…

• Dibi, LeanMapper, Doctrine2, vlastní…

• Nette\Database tvoří nadstavbu PDO a je inspirováno NotORM. (Jakub Vrána)

• Databáze se ptá opravdu efektivně (žádné SELECT * FROM).

• Ačkoliv se ukazuje, že na SELECT * FROM není nic špatného…

• Ale není to ORM. Vadí to však? Jak kdy a jak komu.

• Umí udělat v šabloně nesmyslný „bordel“ ( ->related(spojovaci_tabulka) ).

Auto-loading tříd

• Require souborů je amatérské a nudné.

• Includují se pouze ty soubory, které se

skutečně použijí.

• Nette\Loaders\RobotLoader

RobotLoader je extrémně pohodlná a návyková droga. Budete mít problém

přestat, budete mít problém uvědomit si, že není vždy k dispozici. Nehodlám

se ho však nikdy vzdát. Nikdy… (-:

Nette\Object

• Taťka všech objektů, přinášející „Syntactic sugar “ do vašich tříd.

• Dělá třídy striktní (PHP umožňuje zapisovat do neexistujících proměnných).

• Dokáže za určitých okolností imitovat gettery a settery.

• Umožňuje sebereflexi objektu a to včetně anotací.

• Umí toho mnohem více. Callbacky, události, rozšiřující metody…

Nette\Application\Application, Nette\Application\Diagnostics\RoutingPanel, Nette\Application\Routers\SimpleRouter, Nette\ArrayList, Nette\Caching\Cache, Nette\Caching\OutputHelper, Nette\Caching\Storages\DevNullStorage, Nette\Caching\Storages\FileJournal, Nette\Caching\Storages\FileStorage, Nette\Caching\Storages\MemcachedStorage, Nette\Caching\Storages\MemoryStorage, Nette\Callback, Nette\Application\PresenterFactory, Nette\ComponentModel\Component, Nette\Config\Adapters\IniAdapter, Nette\Config\Adapters\NeonAdapter, Nette\Config\Adapters\PhpAdapter, Nette\Config\Compiler, Nette\Config\CompilerExtension, Nette\Config\Configurator, Nette\Config\Loader, Nette\Database\Diagnostics\ConnectionPanel, Nette\Database\Drivers\MsSqlDriver, Nette\Application\Responses\FileResponse, Nette\Database\Drivers\MySqlDriver, Nette\Database\Drivers\OciDriver, Nette\Database\Drivers\OdbcDriver, Nette\Database\Drivers\PgSqlDriver, Nette\Database\Drivers\SqliteDriver, Nette\Database\Reflection\ConventionalReflection, Nette\Database\Reflection\DiscoveredReflection, Nette\Database\SqlLiteral, Nette\Database\SqlPreprocessor, Nette\Database\Table\ActiveRow, Nette\Application\Responses\ForwardResponse, Nette\Database\Table\Selection, Nette\Database\Table\SqlBuilder, Nette\DI\ContainerBuilder, Nette\DI\Diagnostics\ContainerPanel, Nette\DI\ServiceDefinition, Nette\DI\Statement, Nette\Diagnostics\Bar, Nette\Diagnostics\BlueScreen, Nette\Diagnostics\FireLogger, Nette\Diagnostics\Logger, Nette\Application\Responses\JsonResponse, Nette\Forms\ControlGroup, Nette\Forms\Rendering\DefaultFormRenderer, Nette\Forms\Rule, Nette\Forms\Rules, Nette\FreezableObject, Nette\Http\Context, Nette\Http\FileUpload, Nette\Http\Request, Nette\Http\RequestFactory, Nette\Http\Response, Nette\Application\Responses\RedirectResponse, Nette\Http\Session, Nette\Http\SessionSection, Nette\Http\UserStorage, Nette\Image, Nette\Latte\Compiler, Nette\Latte\Engine, Nette\Latte\HtmlNode, Nette\Latte\MacroNode, Nette\Latte\Macros\CacheMacro, Nette\Latte\Macros\MacroSet, Nette\Application\Responses\TextResponse, Nette\Latte\Parser, Nette\Latte\PhpWriter, Nette\Latte\Token, Nette\Loaders\AutoLoader, Nette\Mail\MimePart, Nette\Mail\SendmailMailer, Nette\Mail\SmtpMailer, Nette\Reflection\Annotation, Nette\Security\Diagnostics\UserPanel, Nette\Security\Permission, Nette\Application\Routers\CliRouter, Nette\Security\SimpleAuthenticator, Nette\Security\User, Nette\Templating\Template, Nette\Utils\Finder, Nette\Utils\Html, Nette\Utils\Neon, Nette\Utils\Paginator, Nette\Utils\PhpGenerator\ClassType, Nette\Utils\PhpGenerator\Method, Nette\Utils\PhpGenerator\Parameter, Nette\Application\Routers\Route, Nette\Utils\PhpGenerator\Property, Nette\Utils\Tokenizer, Nette\Utils\Validators, NetteModule\MicroPresenter, Nette\Application\Request, Nette\Application\Routers\RouteList, Nette\Config\Extensions\NetteExtension, Nette\Config\Extensions\PhpExtension, Nette\Database\Drivers\Sqlite2Driver, Nette\Database\Table\GroupedSelection, Nette\DI\Container, Nette\Forms\Container, Nette\Forms\Controls\BaseControl, Nette\Forms\Controls\Button, Nette\Forms\Controls\Checkbox, Nette\Forms\Controls\HiddenField, Nette\Application\UI\Control, Nette\Forms\Controls\ImageButton, Nette\Forms\Controls\MultiSelectBox, Nette\Forms\Controls\RadioList, Nette\Forms\Controls\SelectBox, Nette\Forms\Controls\SubmitButton, Nette\Forms\Controls\TextArea, Nette\Forms\Controls\TextBase, Nette\Forms\Controls\TextInput, Nette\Forms\Controls\UploadControl, Nette\Forms\Form, Nette\Application\UI\Form, Nette\Http\Url, Nette\Http\UrlScript,

Shrnutí modelu

• Pro debug je velmi užitečný debugger Tracy.

• Pro práci s DB existuje Nette\Database, nástavba nad PDO.

• Třídy se načítají automaticky, není potřeba require.

• Nette\Object dělá z objektů objekty 2.0…

Nějaké dotazy k modelu nebo k tomu, co jsem doposud říkal?

PRESENTERTen, bez kterého to nejde…

Životní cyklus presenteru

1. Inicializace proměnných parent::startup();

2. Alternativa k render metodě action<Action>();

3. Zpracování signálů (AJAX) handle<Signal>();

4. Předání společných prom. beforeRender();

5. Předání dat do šablony render<View>();

6. … ??? Cache ??? shutdown();

Formuláře

• Formuláře jsou obecně velmi náročné a problematické. Proč?

• Jsou pracné. Musíte psát HTML kód…

• Musíte zajistit JavaScriptovou validaci.

• Musíte zajistit serverovou validaci.

• V případě chyby vrátit a vypsat předvyplněný formulář.

• Neudělat bezpečnostní chybu a zajistit zpětnou kompatibilitu.

• Na nic z toho nezapomenout…

Formuláře v Nette

• Snaží se předchozí problémy maximálně potlačit…

• Generuje HTML5 validační pravidla.

• Poskytuje jednoduchý způsob překladu formulářů.

• Ošetřuje XSS, CSRF, UTF-8 attack, …

• Umožňuje jednoduše ovlivnit výstupní kód. Někdy…

Nette\Application\UI\Form• Dědí od obecné třídy Nette\Forms\Form {control signInForm}

protected function createComponentSignInForm() {$form = new \Nette\Application\UI\Form;$form->addText('name', 'Jméno:');$form->addPassword('password', 'Heslo:');$form->addSubmit('login', 'Přihlásit se');$form->onSuccess[] = $this->signInFormSubmitted;return $form;

}

public function signInFormSubmitted(UI\Form $form) {$values = $form->getValues();// ... $this->flashMessage('Byl jsi úspěšně přihlášen.');$this->redirect('Homepage:');

}

Routování URL adres

• Routování je obousměrné překládání mezi URL a akcí presenteru.

• Nemusíme se v šablonách (a presenterech) starat o URL adresy.

• Tvar odkazů lze velmi snadno ovlivnit. Globálně.

• SimpleRouter (pokud nelze použít mod_rewrite) – parametry v URL

• CliRouter, možno vytvořit si vlastní router

• Podpora ONE_WAY jednosměrek, HTTPS, překladů, filtrů…

• Debugger panel, SEO a kanonizace

<a n:href="Product:detail $productId">detail produktu</a>

Dependency Injection

„Podstatou Dependency Injection (DI) je odebrat třídám zodpovědnost

za získávání objektů, které potřebují ke své činnosti (tzv. služeb) a místo toho

jim služby předávat při vytváření.“

• Uvedením závislostí v konstruktoru presenteru. Nepraktické.

• Injekce závislostí pomocí setrů. Lepší, ale moc práce.

• Inject* metody, předek – objekt obsahující závislosti.

• Magické injektování pomocí anotace @inject. Trošku kouzlo…

AJAX / AJAJAsynchronous JavaScript and XML1) / JSON2)

1) Extensible Markup Language2) JavaScript Object Notation

Legen… wait for it…

…dary, legendary

• XMLHttpRequest – „WTF object“

• S AJAXem to není tak jednoduché…

• Snižuje zátěž webového serveru. To ano, ale také zvyšuje počet HTTP požadavků…

• Jak je to s tlačítkem zpět / vpřed a historií?

• Jak je to s adresou URL? Reprezentuje aktuální stav?

• Je potřeba signalizovat průběh AJAX požadavku.

Ukazuje se, že většina věcí je dnes již vyřešena, nic to však nemění na tom, že je třeba hooodně promyslet, jestli je použití AJAXu pro daný účel vhodné.

AJAX prakticky (Nette)

Je potřeba několik jednoduchých kroků:

1. Vyvolat event na straně klienta (JS) – není vazba na konkrétní JS knihovnu

2. Ten na pozadí zavolá handle* metodu z presenteru

3. Vrátíme data do šablony (payload, klasickým způsobem)

4. Invalidujeme (čti překreslíme) snippet (čti logickou část stránky)

Více v ukázce…

Shrnutí presenteru a AJAXu

• Presenter má vlastní životní cyklus. Každá metoda je vhodná na něco jiného.

• Pro tvorbu formulářů existuje Nette\Application\UI\Form.

• Tvar URL adres lze velmi dobře ovlivnit pomocí tzv. routování.

• Snažíme se dodržovat Dependency Injection, je to jednoduché a pohodlné.

• Práce s AJAXem je díky frameworku velmi jednoduchá a přímočará.

Nějaké dotazy k presenterům nebo k tomu, co jsem doposud říkal?

DĚKUJI ZAPOZORNOST

ZEMINEM.CZFRESH-HOSTING.CZ