Lekce 3 - První aplikace v Nette
Z minulé lekce, Nette sandbox a IDE, máme vše připraveno pro vývoj v Nette frameworku.
V dnešním tutoriálu si ukážeme tvorbu první jednoduché aplikace. Na ní si vysvětlíme základní strukturu a konfiguraci frameworku a především základy MVP.
Volba aplikace
Výběr vhodné aplikace, na které bychom si mohli demonstrovat vše
potřebné, nebyl úplně snadný, ale nakonec se vítězem stala jednoduchá
kalkulačka, jejíž screenshot vidíte níže. Takže když už víme v čem a
co budeme dělat, tak hurá do práce!

Instalace Nette
Abychom mohli začít programovat, musíme si Nette zase nainstalovat. Buď
si Nette klasicky stáhneme a
rozbalíme do dané projektové složky z oficiální stránky. Projekt si
pojmenujeme např. nette-calculator
.
Pokročilejší uživatelé mohou použít zase Composer. Když už máme Composer připravený, stačí si otevřít danou projektovou složku a spustit konkrétní příkaz, který zařídí celou instalaci Nette a zkontroluje i potřebné závislosti.
Nový projekt vytvoříme trochu jiným příkazem, než minule:
Nevytváříme už totiž sandbox, který má requirement checker a další
"zbytečnosti". Tímto příkazem se nám vytvořila základní struktura
projektu ve složce nette-calculator/
. K ní si už nepozměníme
soubor .htaccess
pro automatické přesměrování do složky
www/
, kde se nachází soubor index.php
, kterým se
celá aplikace spouští. Vytvoříme si přímo vestavěný server PHP.
Otevřete si v kořenovém adresáři projektu konzoli a vepište tento
kód:
php -S localhost:8000 -t www
Konzoli je třeba nechat zapnutou, ať naše webová aplikace běží. Dá se říci, že vaše konzole je nyní takový PHP server.
Nyní stačí zadat do webového prohlížeče URL:
http://localhost:8000/
Měli byste vidět tuto základní stránku Nette webového projektu (v případě sandboxu zde budou ještě nějaké informace navíc):

Pokud se vám tato stránka z nějakého důvodu nezobrazuje, pravděpodobně
je něco špatně s vaší konfigurací projektu, takže doporučuji znovu
poctivě projít návod i odkazy výše nebo třeba zkusit druhý způsob
instalace. A když už opravdu nebudete vědět kudy kam, můžete mi vždycky
napsat do komentářů pod článek
MVP
Teď, když již máme vše připravené, můžeme začít programovat samotnou kalkulačku. Jen jedna důležitá otázka, odkud začít? Za sebe mohu doporučit 3 způsoby postupu:
1) Postup od Pohledu
V tomto postupu se nejdříve zamyslíme, co chceme vlastně na dané webové stránce zobrazit. Podle toho si navrhneme šablonu (template), kterou ale musíme vyplnit potřebnými daty. Takže následně navrhneme presenter, který potřebná data předává do šablony. Ten ale musí tato data získat z modelu, takže nakonec naprogramuje onen model, který tato data dodává např. z databáze.
2) Postup od Modelu
Zde je postup v podstatě opačný. Nejdříve se zamyslíme, jaká data budeme potřebovat zobrazit. K získání těchto dat si vytvoříme model. Dále potřebujeme tato data zpracovat a předat do šablony a k tomu si opět uděláme potřebný presenter. Nakonec navrhneme šablonu, kde se získaná data zobrazí do podoby webové stránky.
3) Kombinace předchozích
Tento postup si bere z každého trochu. Vytváříme postupně šablony i modely a pak se je snažíme pomocí presenterů lepit dohromady. Tohle je asi nejpoužívanější metoda, která nabízí tu výhodu, že můžeme střídavě postupovat z obou směrů vývoje, což je v praxi asi nejpoužitelnější. Jen musí člověk dát pozor, aby se v tom neztratil, zachoval rozdělení funkčnosti modelů a presenterů a nelepil dohromady ošklivé konstrukce, které mu zkrátka vyplynuly střetem modelu a šablony.
Já v tomto případě zvolím postup číslo dvě, protože se domnívám, že se pro naši kalkulačku více hodí. Takže začneme hezky od Modelu.
Model
app/Model/CalculatorManager.php
Řekněme, že naše kalkulačka bude mít 4 základní operace tj.
sčítání, odčítání, násobení a dělení. Tyto operace umístíme do
modelu, protože nám vracejí výsledky, tedy naše data. Vytvoříme si
složku app/Model/
, kde vytvoříme soubor
CalculatorManager.php
s naší třídou modelu
CalculatorManager
, která používá PHP trait
Nette/SmartObject
a definuje naše 4 operace:
<?php declare(strict_types=1); namespace App\Model; use Nette\SmartObject; /** * Model operací kalkulačky. * @package App\Model */ class CalculatorManager { use SmartObject; /** * Sečte daná čísla a vrátí výsledek. * @param int $x první číslo * @param int $y druhé číslo * @return int výsledek po sčítání */ public function add(int $x, int $y) { return $x + $y; } /** * Odečte druhé číslo od prvního a vrátí výsledek. * @param int $x první číslo * @param int $y druhé číslo * @return int výsledek po odčítání */ public function subtract(int $x, int $y) { return $x - $y; } /** * Vynásobí daná čísla a vrátí výsledek. * @param int $x první číslo * @param int $y druhé číslo * @return int výsledek po násobení */ public function multiply(int $x, int $y) { return $x * $y; } /** * Vydělí první číslo druhým bezezbytku a vrátí výsledek. * @param int $x první číslo * @param int $y druhé číslo; nesmí být 0 * @return int výsledek po dělení bezezbytku */ public function divide(int $x, int $y) { return round($x / $y); } }
Můžete si povšimnout, že jelikož jsem se rozhodl provádět operace v celých číslech, tak chci tuto vlastnost zachovat i u dělení, tudíž výsledek zaokrouhluji na celá čísla. Dále si bystřejší z vás určitě všimli, že není ošetřeno dělení nulou. To však není chyba a my se k tomu ještě vrátíme.
Úplně na začátku jsem se rozhodl využívat tzv. striktní typy. To je v PHP verze 7 novinka a zakazuje nám to použít jiný datový typ do funkce, než který je tam definovaný. Například volání funkce:
multiply(2.3, 5);
vyvolá chybu, protože chceme násobit číslo 2.3 (datový typ
float
), funkce podporuje však pouze celé číslo
(int
).
Základní operace bychom tedy měli, to však ještě není všechno. Jelikož by model měl být rozšiřitelný a podle MVP bychom při změně modelu nejlépe neměli měnit ani presenter, ani šablonu, přidáme si ještě jednoduché rozhraní, která nám tyto vlastnosti zajistí. Jen poznamenám, že tyto vlastnosti lze získat i pomocí reflexe, ale té se zde věnovat nechci. To znamená, že přidáme ještě tyto metody a konstanty:
// ... /** Definice konstant pro operace. */ const ADD = 1, SUBTRACT = 2, MULTIPLY = 3, DIVIDE = 4; /** * Getter pro existující operace. * @return array asociativní pole konstant pro operace a jejich slovního pojmenování */ public function getOperations() { return array( self::ADD => 'Sčítání', self::SUBTRACT => 'Odčítání', self::MULTIPLY => 'Násobení', self::DIVIDE => 'Dělení' ); } /** * Zavolá zadanou operaci a vrátí její výsledek. * @param int $operation zadaná operace * @param int $x první číslo pro operaci * @param int $y druhé číslo pro operaci * @return int|null výsledek operace nebo null, pokud zadaná operace neexistuje */ public function calculate(int $operation, int $x, int $y) { switch ($operation) { case self::ADD: return $this->add($x, $y); case self::SUBTRACT: return $this->subtract($x, $y); case self::MULTIPLY: return $this->multiply($x, $y); case self::DIVIDE: return $this->divide($x, $y); default: return null; } } // ...
Nyní jsme schopni přidat další operaci do modelu a přitom v presenteru i v šabloně nemusíme změnit v podstatě nic. A to je z modelu i z dnešní lekce už opravdu vše.
V další lekci, Dokončení kalkulačky v Nette, se podíváme na presenter, routování, formuláře
a šablony v Nette.