bachelor thesis
TRANSCRIPT
Vysoká škola ekonomická v Praze
Fakulta informatiky a statistiky
Katedra informačního a znalostního inženýrství
Studijní program: Aplikovaná informatika
Obor: Informatika
Srovnání PHP frameworků Phalcon,
Nette a Zend
BAKALÁŘSKÁ PRÁCE
Student : Jiří Rebenda
Vedoucí : Ing. et Ing. Stanislav Vojíř
Oponent : Ing. Jiří Zumr
2014
Prohlášení:
Prohlašuji, že jsem bakalářskou práci zpracoval samostatně a že jsem uvedl všechny použité
prameny a literaturu, ze které jsem čerpal.
V Praze dne 12. května 2014 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Jiří Rebenda
Poděkování
Zde bych rád poděkoval Ing. et Ing. Stanislavu Vojíři jakožto vedoucímu bakalářské práce
za podnětné připomínky a čas, který jí věnoval. Za provedenou gramatickou korekturu rov-
něž děkuji svým rodičům.
Abstrakt
Dostupnost jazyka PHP a jeho rozšíření napříč vývojáři webových aplikací zapříčiňuje exis-
tenci mnoha projektů na něm postavených. S růstem jeho popularity rostly (a pravděpodobně
do budoucna růst budou) i požadavky na něj kladené. Mnoho z nich nemusí přímo souviset
s jazykem jako takovým, nýbrž s potřebami danými vnějšími okolnostmi (rozvoj Internetu
apod.). Jednou z reakcí na existencí stále se opakujících se problémů a jejich rostoucí kom-
plexitu jsou speciální knihovny známé též jako frameworky.
Tato bakalářská práce se věnuje porovnání tří vybraných frameworků (Zend Framework 2.3,
Nette 2.1.2 a Phalcon 1.3.1). V první (kratší) části jsou zprvu deklarovány některé základní
pojmy a omezení daná prostředím PHP. Dále jsou spolu s popisem jednotlivých kritérií, na
základě kterých jsou frameworky dále porovnávány, uvedeny otázky, na něž jsou v hlavní
části práce poskytnuty (více či méně explicitní) odpovědi.
Druhá – teoreticko-praktická část – se již zabývá rozborem frameworků v souvislosti s defi-
novanými problémovými oblastmi. Smyslem popisu aplikačního rozhraní frameworků spolu
s ukázkami kódu je popsat čtenáři eventuální rozdíly v pojetí řešení některých vybraných
problémů. Práce se rovněž okrajově dotýká způsobů, jakými lze hodnotit jejich relativní ob-
líbenost.
Výstupem práce není kladné, či záporné hodnocení některého z frameworků. Práce by nao-
pak měla být chápána jako jeden z možných zdrojů např. při rozhodování se, zda některému
z frameworků věnovat vyšší pozornost, či nikoliv. Dílčím přínosem je i fakt, že jsou potvr-
zeny některé axiomatické předpoklady (např. co se týče jejich rychlosti a oblíbenosti).
Klíčová slova
PHP, porovnání frameworků, webový vývoj, Zend, Nette, Phalcon.
Abstract
Wide usage of the PHP language across web developers and its good availability results in
existence of many projects built on it. Unfortunately, due to the growth of PHP popularity
more requirements are imposed on it. Not all of them tend to be related directly to the lan-
guage itself but they can be affected by the external conditions (like e.g. Internet evolution,
etc.). Special libraries (also known as frameworks) are response to existence of permanently
repetitive tasks and growing complexity of problems being solved not only in the context of
web development.
There are three PHP framework representatives compared in this paper (Zend Framework
2.3, Nette 2.1.2 and Phalcon 1.3.1). In the first section, some fundamental terms are declared
as well as some inherent limitations of the PHP language itself. Further, various comparison
criterions are introduced together with additional research questions which are more or less
answered in the main section.
The second theoretical-practical section analyses the frameworks in the context of the de-
fined problem domains. The main purpose of the application programming interface review
together with included code snippets is to describe possible differences in approaches ap-
plied for some specific problems. Additionally, some options for measuring framework pop-
ularity mentioned in earlier section are used, too.
In the end, frameworks are not evaluated either in positive or negative way. The final eval-
uation remains on the actual reader. The main focus is to provide basic insight into all three
frameworks and possibly to (de)motivate to deeper exploration any of them. Also, as matter
of secondary objectives some axiomatic assumptions are validated (like speed and popularity
of the frameworks).
Keywords
PHP, frameworks comparison, web development, Zend, Nette, Phalcon.
Obsah
1 Úvod ........................................................................................................... 1
1.1 Cíle práce ............................................................................................................... 1
1.2 Předpoklady a omezení práce .............................................................................. 2
1.3 Struktura práce ..................................................................................................... 2
2 Rešerše stávajících prací ........................................................................... 3
3 PHP frameworky .......................................................................................... 5
3.1 Základní termíny ................................................................................................... 5
3.1.1 PHP (Hypertext Preprocessor) ................................................................ 5
3.1.2 PHP framework......................................................................................... 6
3.1.3 Návrhové vzory ........................................................................................ 7
3.2 Oblíbenost PHP frameworků ................................................................................ 9
3.2.1 Popularita ve vyhledávači Google .......................................................... 9
3.2.2 Popularita v diskuzních fórech a sociálních sítích ............................... 9
3.2.3 Vývojářská aktivita ................................................................................. 10
3.2.4 Počet pracovních nabídek ..................................................................... 10
3.3 Kritéria pro porovnání ........................................................................................ 10
3.3.1 Technické požadavky frameworku ....................................................... 10
3.3.2 Autoloading tříd ..................................................................................... 10
3.3.3 MVC ......................................................................................................... 11
3.3.4 DI (Dependency Injection) ..................................................................... 11
3.3.5 Komponentový vývoj ............................................................................. 12
3.3.6 Šablonový systém .................................................................................. 13
3.3.7 Formuláře ............................................................................................... 14
3.3.8 Session a Cookies ................................................................................. 14
3.3.9 Databázová abstrakce ........................................................................... 15
3.3.10 Autorizace, autentizace ......................................................................... 16
3.3.11 Lokalizace ............................................................................................... 17
3.3.12 Využití cache .......................................................................................... 17
3.3.13 Ladění a zpracování chyb ..................................................................... 18
3.3.14 Rychlost .................................................................................................. 19
3.3.15 Ostatní ..................................................................................................... 22
4 Porovnání PHP frameworků ..................................................................... 23
4.1 Technické požadavky frameworku .................................................................... 23
4.1.1 Zend ........................................................................................................ 23
4.1.2 Nette ........................................................................................................ 23
4.1.3 Phalcon ................................................................................................... 24
4.2 Autoloading tříd .................................................................................................. 24
4.2.1 Zend ........................................................................................................ 24
4.2.2 Nette ........................................................................................................ 25
4.2.3 Phalcon ................................................................................................... 25
4.3 MVC ...................................................................................................................... 26
4.3.1 Zend ........................................................................................................ 26
4.3.2 Nette ........................................................................................................ 29
4.3.3 Phalcon ................................................................................................... 33
4.4 DI (Dependency Injection) .................................................................................. 35
4.4.1 Zend ........................................................................................................ 35
4.4.2 Nette ........................................................................................................ 37
4.4.3 Phalcon ................................................................................................... 39
4.5 Komponentový vývoj .......................................................................................... 40
4.5.1 Zend ........................................................................................................ 40
4.5.2 Nette ........................................................................................................ 41
4.5.3 Phalcon ................................................................................................... 43
4.6 Šablonový systém .............................................................................................. 44
4.6.1 Zend ........................................................................................................ 44
4.6.2 Nette ........................................................................................................ 47
4.6.3 Phalcon ................................................................................................... 49
4.7 Formuláře ............................................................................................................ 51
4.7.1 Zend ........................................................................................................ 51
4.7.2 Nette ........................................................................................................ 54
4.7.3 Phalcon ................................................................................................... 56
4.8 Session a Cookies .............................................................................................. 58
4.8.1 Zend ........................................................................................................ 58
4.8.2 Nette ........................................................................................................ 60
4.8.3 Phalcon ................................................................................................... 61
4.9 Databázová abstrakce ........................................................................................ 63
4.9.1 Zend ........................................................................................................ 63
4.9.2 Nette ........................................................................................................ 65
4.9.3 Phalcon ................................................................................................... 67
4.10 Autorizace, autentizace ...................................................................................... 71
4.10.1 Zend ........................................................................................................ 71
4.10.2 Nette ........................................................................................................ 72
4.10.3 Phalcon ................................................................................................... 73
4.11 Lokalizace ............................................................................................................ 73
4.11.1 Zend ........................................................................................................ 73
4.11.2 Nette ........................................................................................................ 74
4.11.3 Phalcon ................................................................................................... 75
4.12 Využití cache ....................................................................................................... 75
4.12.1 Zend ........................................................................................................ 75
4.12.2 Nette ........................................................................................................ 77
4.12.3 Phalcon ................................................................................................... 78
4.13 Ladění a zpracování chyb .................................................................................. 80
4.13.1 Zend ........................................................................................................ 80
4.13.2 Nette ........................................................................................................ 81
4.13.3 Phalcon ................................................................................................... 82
4.14 Rychlost ............................................................................................................... 84
4.14.1 Celkové zpracování požadavku ............................................................ 84
4.14.2 Výkonnost databázové vrstvy ............................................................... 87
4.15 Ostatní ................................................................................................................. 92
4.15.1 Licenční omezení ................................................................................... 92
4.15.2 Dokumentace ......................................................................................... 93
4.15.3 Komunita spojená s frameworkem ....................................................... 93
4.15.4 Počet pracovních nabídek ..................................................................... 95
4.15.5 Existující rozšíření ................................................................................. 95
5 Závěr ......................................................................................................... 97
Terminologický slovník ................................................................................... 98
Seznam literatury ........................................................................................... 101
Seznam obrázků a tabulek ............................................................................ 108
Základní text .............................................................................................................. 108
Seznam obrázků ............................................................................................. 108
Seznam tabulek .............................................................................................. 108
Přílohy ....................................................................................................................... 109
Seznam tabulek .............................................................................................. 109
Příloha A: Výsledky rychlostního měření ..................................................... 110
A.1 Celkové zpracování požadavku ....................................................................... 110
A.2 Výkonnost databázové vrstvy .......................................................................... 119
1 Úvod 1
1 Úvod Tvorba softwaru zahrnuje celou řadu jak obecných tak i specifických činností a bezpochyby
klade poměrně vysoké nároky na osoby zodpovědné za jeho samotnou realizaci. Zejména
pak v kontextu vývoje webových/internetových aplikací je nutné podotknout (odhlédneme-
li od obecných požadavků jako jsou např. zkušenosti vývojáře), že mezi běžné kvalifikační
požadavky patří alespoň základní znalost hned několika různých technologií, přičemž se zá-
roveň předpokládá hlubší znalost alespoň jedné z nich.
K základním požadavkům patří znalost jednoho konkrétního programovacího/skriptovacího
jazyka určeného k vývoji na straně serveru (např. PHP, ASP .NET C#, …) a sloužícího k ob-
sloužení vnějších požadavků (např. požadavek internetového prohlížeče ke stažení webové
stránky), tak celá řada klientsky založených (angl. client-side) jazyků orientovaných hlavně
na sémantickou a grafickou část odpovědi vrácené serverem (HTML stránka, CSS, JS, …).
Nadstavbou je pak znalost práce s nejrůznějšími knihovnami a jedná-li se o jazyk PHP, který
je v současnosti vůbec nejpopulárnějším webově orientovaným jazykem1, pak se tímto nej-
častěji rozumí znalost některého z PHP frameworků. Náplní této práce je popis tří vybraných
zástupců lišících se svým pojetím, rozsahem i stářím. Jelikož každý může od frameworku
očekávat něco jiného, je celkové hodnocení jednotlivých frameworků ponecháno na čtenáři.
Práce by měla posloužit jako výchozí bod např. při rozhodování, kterému frameworku vě-
novat více pozornosti v závislosti na konkrétních preferencích čtenáře.
1.1 Cíle práce
Vycházíme-li z předchozího rozdělení, tato práce se zabývá jedním z dílčích aspektů souvi-
sejících s vývojem na straně serveru, a to konkrétně v jazyce PHP za využití několika vy-
braných a v současnosti veřejně dostupných frameworků: Zend, Nette, Phalcon. Primárním
cílem práce je představení těchto frameworků, popis jejich charakteristických rysů, mož-
ností, které nabízejí a praktické porovnání jejich použitelnosti z pohledu vývojáře.
Hlavním důvodem volby právě těchto tří frameworků je zájem autora porovnat různé pří-
stupy pro řešení běžných problémů v rámci vývoje webových aplikací, do jaké míry jsou
jednotlivé problémové oblasti pokryty frameworkem a případně do jaké míry je ponechán
prostor vývojáři např. k úpravě jeho standardního chování apod. Důležitým výstupem práce
je jejich pozitivní, avšak kritické porovnání na základě definovaných kritérií, která jsou uve-
dena v první části práce.
1 Vyplívá z dat zveřejněných (Q-Success, 2014).
1 Úvod 2
1.2 Předpoklady a omezení práce
Práce je určena všem zájemcům o praktický vývoj v PHP za použití frameworků. Předpo-
kládá se alespoň základní znalost problematiky objektově orientovaného programování
(OOP) a to ideálně v návaznosti na podporu OOP konstrukcí ze strany PHP. Dále orientace
v prostředí PHP, případně jiného obdobného jazyka. Podmínkou je rovněž znalost obecných
principů souvisejících s vývojem webových stránek a aplikací a povědomí o existenci návr-
hových vzorů.
1.3 Struktura práce
Práce je rozdělena na dvě části. První část práce seznamuje čtenáře s vybranými hledisky
vývoje webových aplikací za podpory PHP frameworků. V této části jsou definovány zá-
kladní pojmy použité v práci. Rovněž jsou popsány některé problémy a omezení související
s vývojem webových aplikací, obzvláště v souvislosti s nasazením některého z frameworků.
V návaznosti na jejich identifikaci jsou následně definována kritéria, na základě kterých je
porovnání realizováno. Druhá část obsahuje již samotné srovnání frameworků, přičemž
v rámci jedné problémové oblasti jsou porovnány všechny tři frameworky navzájem a to
vždy v pořadí Zend, Nette, Phalcon. Struktura a způsob porovnání frameworků jsou převzaty
a vychází především z (Křižan, 2010), případně jiných podobně zaměřených prací.
2 Rešerše stávajících prací 3
2 Rešerše stávajících prací Souhrn existujících prací zabývajících se tématikou komparace PHP frameworků lze v zá-
sadě rozdělit na dva typy:
Práce zabývající se komplexním popisem jednoho či více frameworků, kdy jsou
srovnávány na základě několika parametrů, tento druh prací lze rozdělit ještě na další
dva samostatné podtypy:
o Srovnání frameworků v rámci jazyka PHP,
o Srovnání frameworků různých platforem.
Srovnání frameworků na základě jediné vybrané oblasti, kterou frameworky nabí-
zejí.
Velmi komplexní srovnání čtyř vybraných frameworků (CodeIgniter, Zend, Prado, Yii) po-
dává (Křižan, 2010). Autor věnoval poměrně rozsáhlý prostor teoretické části, ve které po-
pisuje problematiku tvorby webových aplikací v prostředí PHP a stejně tak vyzdvihuje
významné vlastnosti, kterými se frameworky obecně vyznačují. Popsány jsou základní ar-
chitektonické vzory a požadavky na framework. Na tuto část plynule navazuje oddíl věno-
vaný elementární charakteristice zvolených frameworků včetně údajů o šíři komunity, která
je s nimi spojena. Následně jsou definována kritéria, na základě kterých autor provedl srov-
nání a to včetně metrik, které jsou ale ve všech případech hodnocených kritérií prakticky
totožná a spočívají v identifikaci toho, zdali daný framework konkrétní oblast podporuje či
nikoliv včetně případného komentáře. Autor na závěr neopomenul ani interpretaci výsledků
srovnání, které jsou popsány relativně výstižně a jasně.
Z prací věnovaných více než jednomu PHP frameworku lze zmínit (Koščo, 2013), ve které
jsou porovnány frameworky Zend a Symfony. Za užitečnou část práce lze považovat už jen
fakt, že autor v samostatné kapitole demonstroval důvody, proč pro porovnání zvolil právě
tyto dva zástupce – faktor oblíbenosti je zde doložen exaktními údaji z veřejně dostupných
internetových zdrojů (diskuzní fóra, popularita ve vyhledávačích apod.). Struktura hodno-
cení spočívá v demonstraci možností frameworků vytvořením vzorové aplikace v každém
z nich. Vyhodnocení opět spočívá ve stanovení vah kritérií, které jsou na konci interpreto-
vány za použití tzv. Fullerovy2 metody.
Z dalších prací věnujících se však rozboru pouze jednoho frameworku lze zmínit bakalář-
skou práci o českém frameworku Nette (Tölg, 2012). Zde autor kromě obecně platných prin-
cipů popisuje i konkrétní příklady využití návrhových vzorů, které Nette uplatňuje.
2 Metoda spočívá v postupném porovnání dvojic kritérií mezi sebou a určení, zdali je
první kritérium důležitější než druhé, případně zda se jejich důležitost rovná. (Žižka,
2008)
2 Rešerše stávajících prací 4
Samozřejmostí jsou zmínky i o některých jeho specifických vlastnostech, které např. jiné
frameworky vůbec nenabízejí. Celkový dojem z kvality práce však mírně zhoršuje poměrně
familiární vyjadřování autora a zhoršená čitelnost uváděných výpisů kódu.
K dispozici jsou i práce orientované na srovnání některého z PHP frameworků s framewor-
kem určeným pro jinou platformu, jak představuje ve své relativně rozsáhlé práci (Frank,
2013). Délka je ovlivněna především tím, že autor rozpracoval i tzv. zadavatelsko-analytic-
kou část pro vytvoření vzorové aplikace a mj. také množstvím kódu, kterými autor demon-
stroval jejich praktické využití. Autor popisuje zvolená kritéria jasně a srozumitelně
a nezahlcuje čtenáře implementačními detaily během jejich srovnávání, což eventuální zá-
jemce o daný framework vybízí k dohledání těchto informací z jiného zdroje (např. doku-
mentace).
Pravděpodobně vůbec nejznámějšímu frameworku Zend je věnována pozornost hned v ně-
kolika pracích. Např. (Kutišová, 2013) srovnává jeho 2 majoritní verze a změny ke kterým
došlo v rámci novější verze a to opět včetně vytvoření vzorové aplikace v obou verzích.
3 PHP frameworky 5
3 PHP frameworky Vytvoření „dokonalé“ aplikace, ať již webové či desktopové, je snem snad každého, kdo se
na jejím vývoji podílí. Pakliže framework obecně je považován za nástroj napomáhající
k dosažení tohoto cíle, je vhodné pokusit se určit důvody, které tento názor podporují.
Následující část má za cíl v úvodu stručně popsat důležité termíny, které jsou v práci použity
a představit čtenáři základní informace o jazyku PHP, jeho specifických možnostech,
zejména pak v kontextu PHP frameworků. Dále jsou představeny obecné požadavky na fra-
mework a v souladu s tím i výčet jejich vybraných charakteristik, spolu s dalšími termíny
souvisejícími s vývojem webových aplikací. Rovněž jsou uvedeny příklady frameworků
a část je věnována i přehledu jejich „oblíbenosti“.
3.1 Základní termíny
Tato část si klade za cíl stručně charakterizovat vybrané pojmy, které lze z povahy práce
požadovat za fundamentální. Jelikož jsou však tyto termíny zároveň popsány v mnoha jiných
pracích, je kladen důraz na identifikaci méně zřejmých faktorů a důsledků např. z použití
frameworku, souvisejících zejména s jejich reálným nasazením. Vzhledem k charakteru
práce jsou okrajově zmíněny i některé další nepřímo související pojmy či problémy týkající
se návrhu aplikace obecně.
3.1.1 PHP (Hypertext Preprocessor)
PHP je dynamický interpretovaný skriptovací jazyk, který je převážně určen k vývoji webo-
vých stránek a aplikací a vyznačuje se tím, že jej lze zakomponovat přímo do HTML (The
PHP Group, 2014) a umožňuje tak tvorbu dynamických a interaktivních webových stránek
(PHP 5 Tutorial, 2014).
Fakt, že se jedná právě o dynamický a skriptovací jazyk je kruciální, jelikož z něj plynnou
v porovnání s jinými platformami mj. tyto důsledky:
Skript je při každém požadavku interpretován tzn., dochází k jeho opětovnému par-
sování (analýze), interpretaci a vykonání, na rozdíl od kompilovaných jazyků, kde
tento proces probíhá zpravidla pouze jednou. (IBM Corporation, 2010)
Při použití interpretovaného jazyka rovněž odpadá nutnost při každé změně celý pro-
gram rekompilovat (Vanguard Software Corporation, 2013)
Ve srovnání se staticky typovanými jazyky je typ proměnné určen za běhu, přičemž
během vykonání skriptu může dojít i k jeho změně. Toho lze s výhodou využít v celé
3 PHP frameworky 6
řadě situací, zároveň se ale relativně zvyšuje potenciální chybovost, jelikož je chyba
detekována až za běhu skriptu.
PHP a OOP (objektově orientované programování)
Současná podoba OOP modelu vychází z jeho poslední majoritní verze 5 (PHP: Introduction
- Manual, 2014), kdy byl kompletně přepsán a doplněn o nové možnosti. PHP podporuje
většinu obvyklých OOP konstrukcí (abstrakce, třídy, dědičnost, viditelnost, …) známých
např. ze silně OOP jazyků (např. C++, Java, C#, …), avšak některé z nich jsou podporovány
jen částečně a s jistými omezeními (např. přetěžování metod).
OOP model je zároveň rozšířen o některé zvláštní konstrukce, jako jsou např. tzv. magické
metody3 (angl. magic methods), jejichž znalost je důležitá nejen pro obecnou práci s objekty
(konstrukce/destrukce instancí), ale i pro další řadu specifických činností, jelikož umožňují
dosáhnout úspory kódu, potažmo času. Z hlediska nutnosti znalosti jejich existence je nutné
je považovat za esenciální, jelikož principů magických metod využívají typicky právě nej-
různější PHP knihovny/frameworky, o kterých je řeč dále.
3.1.2 PHP framework
Pojem framework lze v obecném měřítku chápat jako „souhrn principů, myšlenek, které jsou
používány v rámci rozhodování, či strukturu, která podporuje určitou činnost“ (framework
- definition of framework by Macmillan Dictionary, 2014). V kontextu softwarového vývoje
lze pak uvést odvozenou definici, která říká, že „framework je určitá knihovna, která
poskytuje základní podpůrnou strukturu pro vývoj aplikací pro konkrétní prostředí“
(Application Framework, 2014).
Z praktického hlediska pak framework4 představuje určitou sadu tříd, knihoven a nástrojů,
jehož cílem by mělo být usnadnění práce při vývoji aplikací. (Tölg, 2012) Možnosti daného
frameworku jsou pak samozřejmě dány jeho aplikačním rozhraním (dále jen API5), jehož
návrh může ovlivnit i použitelnost frameworku jako celku. Podstatným znakem frameworku
je dle (Křižan, 2010) to, že třídy v něm obsažené mají implicitně definováno určité chování,
které by mělo být z principu výhodné a proto i užitečné.
3 Seznam všech magických metod je k dispozici na http://www.php.net/manual/en/lan-
guage.oop5.magic.php.
4 Nebude-li dále uvedeno jinak, má se na mysli vždy PHP framework.
5 Z anglického Application Programming Interface.
3 PHP frameworky 7
Frameworků určených pro jazyk PHP existuje celá řada6, přičemž platí, že jsou v tomto ja-
zyce zároveň i napsány. Výjimku tvoří v současnosti jako jeden z mála7 framework Phalcon,
který je vytvořen v jazyce C a je distribuován jako zásuvný modul pro PHP. Z existujících
frameworků, z nichž některé jsou charakterizovány v pracích podobného zaměření, je možné
zmínit např.:
Symfony (http://symfony.com),
CakePHP (http://cakephp.org),
CodeIgniter (http://ellislab.com/codeigniter),
Yii (http://www.yiiframework.com),
Laravel (http://laravel.com).
Omezení
Frameworky zpravidla usnadňují tzv. „opakující se rutinní práci“ a umožňují vývojáři sou-
středit se spíše na implementaci doménové logiky s prostředky daného frameworku či dal-
ších knihoven. Problém však může nastat v případě, že řešený problém nelze s daným
výchozím chováním vyřešit. Na řadě je pak buď přeformulování problému za účelem při-
způsobení se daným možnostem či změna/rozšíření výchozího chování frameworku. Míra
přizpůsobení frameworku daným podmínkám proto hraje důležitou roli z hlediska jeho po-
užitelnosti.
V neposlední řadě je nutné poukázat na fakt, že jakýkoliv realizovatelný problém je možné
s danými prostředky vyřešit zpravidla několika způsoby. Vhodnost řešení je posuzována
subjektivně, protože závisí a zároveň je odrazem zkušeností a je ovlivněna komplexní zna-
lostí frameworku (příkladem může být (ne)vědomé nedodržování konvencí daných frame-
workem atd.).
3.1.3 Návrhové vzory
Jedním z fenoménů, na který dříve či později narazí každý vývojář, je časté opakování stej-
ného kódu v rámci jediného či více programů/skriptů. Možné důsledky a problémy s tímto
spojené jsou motivací k nalezení způsobu, jak tomuto stavu v budoucnu předejít. Jednu
z možných cest nabízí aplikace tzv. „návrhových vzorů, což jsou obecné, znovupoužitelné
6 http://www.bestwebframeworks.com/compare-web-frameworks/php/
7 Jiným zástupcem je framework Yaf (http://www.yafdev.com).
3 PHP frameworky 8
způsoby řešení běžných softwarových problémů“ (Design Patterns, 2014). Zároveň lze kon-
statovat, že „návrhové vzory nejsou hotovým řešením daného problému, nýbrž je lze chápat
spíše jako šablony pro postup jeho řešení“ (Design Patterns, 2014).
V předešlé části byla zmíněna teze, že cílem použití frameworku by mělo být usnadnění
vývoje aplikací. Jak toho lze ale reálně dosáhnout? Nabízí se odpověď, že jsou to právě
návrhové vzory, za pomoci kterých se lze tomuto cíli při nejmenším přiblížit. Vývoj s vědo-
mím existence a především skutečného použití návrhových vzorů vede v ideálním případě
k relativně znovupoužitelnému, lépe udržitelnému a testovatelnému kódu. (Design Patterns,
2014)
MVC (Model View Controller)
„Návrhový vzor MVC patří mezi nejznámější a nejdiskutovanější návrhové vzory“ (Fowler,
a další, 2002) zejména pak v souvislosti s vývojem webových aplikací, jelikož jeho určitou
implementaci obsahují všechny majoritní frameworky. MVC lze považovat za paradigma,
jehož prostřednictvím je aplikační architektura rozdělena na 3 na sobě relativně8 nezávislé
vrstvy:
Model – Vše, co představuje tzv. „business logiku“ aplikace je součástí této vrstvy;
často bývá model chybně interpretován jako databáze, prakticky tato vrstva sice
často s databází pracuje, ale z obecného hlediska lze do této vrstvy zahrnout veškerou
práci s daty, která jsou tak zapouzdřena a oddělena od zbytku aplikace (Křižan,
2010). Ve skutečnosti však model může a často obsahuje celou sekvenci operací než
jen získání či ukládání dat (např. generování objednávky spolu s vystavením faktury
a její následné odeslání e-mailem uživateli apod.).
View (pohled) – „Pohled zobrazuje model“ (Fowler, a další, 2002), resp. data z mo-
delu a to prostřednictvím uživatelského rozhraní (UI – User Interface). Prezentace
dat ve webových aplikacích je nejčastěji dána výstupem do HTML stránky.
Controller (řadič) – Řadič zajišťuje oboustrannou „komunikaci“ mezi vrstvou mo-
delu (např. získání, resp. uložení dat) a pohledem (např. zobrazení, resp. získání dat).
Důsledné rozdělení zodpovědností za každou z oblastí do zvláštních vrstev s sebou přináší
řadu výhod, mezi které patří:
Data jsou oddělena od jejich prezentace, tudíž jedna sada dat může být zobrazena
v různých výstupních formátech.
Pohled může zobrazovat data z různých zdrojů, která jsou mu předána řadičem.
8 Relativní vztah je uveden proto, že jedna z vrstev (řadič) musí v principu fungovat jako
prostředník mezi dalšími dvěma.
3 PHP frameworky 9
Každou z vrstev je možné (v ideálním případě) vytvářet a testovat relativně samo-
statně.
3.2 Oblíbenost PHP frameworků
Následující kapitola představuje stručnou rešerši přístupů k porovnání relativní
„oblíbenosti“ PHP frameworků mezi sebou navzájem (nikoliv tedy v porovnání s jinými
platformami). Metodika porovnání často vychází ze srovnání několika faktorů:
1. Popularita ve vyhledávači Google.
2. Popularita v diskuzních fórech a sociálních sítích (např. www.stackoverflow.com).
3. „Aktivnost vývoje“ – souvisí s počtem přispěvatelů, počtem vydaných verzí apod.
4. Počet pracovních nabídek s požadavkem na znalost konkrétního frameworku.
Z příkladů srovnání tohoto typu lze uvést jednak diplomovou práci (Koščo, 2013) a jednak
z řady „online testů“ např. (Korop, 2013).
3.2.1 Popularita ve vyhledávači Google
Pro zjištění oblíbenosti z pohledu vyhledávání ve vyhledávači Google použil jak (Koščo,
2013), tak i (Korop, 2013) oficiální nástroj společnosti Google - Google Trends9. Omezení
tohoto nástroje uvádí již (Koščo, 2013), z nichž lze podtrhnout zejména faktor volby samot-
ného klíčového slova (existuje více verzí frameworků). Pro doplnění lze poznamenat ještě
další faktor, kterým je rozlišení geografického rozložení, jehož změnou lze docílit zásadního
rozdílu ve výsledcích měření.
3.2.2 Popularita v diskuzních fórech a sociálních sítích
Popularitu v diskuzních a jiných fórech lze sledovat na základě rozdělení jejich typů:
1) fóra věnovaná konkrétnímu frameworku,
počet registrovaných uživatelů,
počet příspěvků.
2) obecně založená fóra obsahující témata i s jinou, byť ne přímo související tématikou.
9 http://www.google.com/trends/
3 PHP frameworky 10
Absolutní hodnoty těchto měření lze získat relativně snadno, jak předkládá (Koščo, 2013).
3.2.3 Vývojářská aktivita
Do této skupiny lze zahrnout hodnocení četnosti vydaných verzí (počet „commitů“ do repo-
sitáře projektu) a počet vývojářů či přispěvatelů projektu.
3.2.4 Počet pracovních nabídek
Obdobně jako při zjišťování oblíbenosti v diskuzních fórech lze i tento faktor relativně jed-
noduše porovnat zadáním dotazu do vyhledávače některého z inzertních serverů. Za předpo-
kladu, že nabídky inzerovaných pracovních pozic odpovídají skutečnosti, může výsledek
porovnání na základě tohoto parametru velmi dobře poukázat na relativní oblíbenost v rámci
daného regionu.
3.3 Kritéria pro porovnání
V nadcházející kapitole jsou popsána kritéria, na základě kterých budou jednotlivé frame-
worky porovnány. Volba kritérií vychází jednak z vlastní zkušenosti autora a jednak z prací
podobného charakteru, zejm. pak z (Křižan, 2010).
3.3.1 Technické požadavky frameworku
S ohledem na skutečnost, že každý framework definuje vlastní systémové požadavky pro
jeho nasazení, jsou v tomto bodě shrnuty požadavky deklarované jeho autory. Je pravidlem,
že kromě základního požadavku, kterým je určitá verze PHP, bývá doporučováno či přímo
vyžadováno i specifické nastavení běhového (angl. runtime) prostředí (např. pomocí PHP
direktiv či aktivací některých rozšíření).
3.3.2 Autoloading tříd
Autoloading je mechanismus umožňující dodatečné nahrávání zdrojových souborů, typicky
obsahující deklarace tříd a rozhraní, až v případě jejich prvního použití. V PHP pro registraci
tzv. autoloaderů (což jsou objekty, které samotný proces provádí) slouží funkce
3 PHP frameworky 11
spl_autoload_register10. Existuje několik přístupů, jakým lze autoloading automatizovat
a proto jsou stručně charakterizovány jednotlivé přístupy všech tří frameworků.
Specifickým často využívaným přístupem je standard PSR-0. Pro účely práce je důležité
zmínit, že PSR-0 vychází z přesně definovaných konvencí, kde struktura zdrojových sou-
borů v rámci adresářové struktury musí reflektovat názvy jmenných prostorů, ve kterých
jsou deklarovány. Přesné podmínky jsou definovány v (PHP Framework Interoperability
Group, 2013).
3.3.3 MVC
Nativní podpora architektury MVC je považována za jeden ze základních požadavků vůbec
a jeho (ne)naplnění je předmětem první porovnávané oblasti. V rámci srovnání je charakte-
rizován tzv. „životní cyklus“ aplikace vytvořené v daném frameworku a možnosti obsluhy
serverových požadavků. Snahou je rovněž identifikovat případně konvence, které frame-
work v souvislosti s tímto vzorem zavádí.
3.3.4 DI (Dependency Injection)
„Dependency Injection je jedním z nejvíce nepochopených konceptů objektově-
orientovaného programování“ (Seemann, Putting Dependency Injection on the map, 2012),
přitom se nejedná o nic jiného, než pojmenování jedné ze základních technik „čistého“
objektově-orientovaného návrhu. Důsledné respektování tohoto paradigmatu znamená při-
způsobení definic tříd, potažmo jejich API, přesvědčení, že každá vnější závislost musí být
objektu předána skrze jeho veřejné rozhraní. „Dependency Injection je souhrnem principů
a návrhových vzorů softwarového návrhu, které umožňují vytvářet kód, který není těsně
svázaný11“ (Seemann, A Dependency Injection tasting menu, 2012).
Z praktického hlediska porozumění principu DI znamená, že výsledný kód navržených tříd
neobsahuje žádné12 skryté závislosti a vše, co třída ke své funkčnosti potřebuje, jí je předáno
z vnějšku, tzn., „že objekty mohou mezi sebou prostřednictvím přesně daných vazeb
navzájem komunikovat s minimální znalostí sebe navzájem“ (Freeman, Freeman, Sierra, &
Bates, 2004). Kód se proto stává relativně udržitelnějším, znovupoužitelným a lépe testova-
telným.
10 http://www.php.net/manual/en/function.spl-autoload-register.php
11 Z angl. tight coupling.
12 V praxi nemusí být tento idealistický stav reálně dosažitelný (např. používání nativních
funkcí apod.), případně není z nejrůznějších důvodů žádoucí.
3 PHP frameworky 12
Na základě (Fowler, Inversion of Control Containers and the Dependency Injection pattern,
2004) a (Seemann, DI patterns, 2012) lze rozlišit 3 základní techniky DI:
Constructor Injection – injektáž závislostí za pomocí konstruktoru,
Property Injection – injektáž závislostí změnou hodnoty veřejné vlastnosti třídy,
Method Injection – injektáž skrze veřejnou metodu třídy.
Relativní výhody a nevýhody těchto přístupů demonstruje (Grudl, DI a předávání závislostí,
2012), kdy zároveň poukazuje na problémy spojené s DI v prostředí jazyka PHP.
V souvislosti s DI bývají rovněž často skloňovány pojmy, jako jsou Inversion of Control
(IOC) a DI Container (DI kontejner) a není překvapením, že s DI velmi úzce souvisí. První
z termínů (IOC) pouze vyzdvihuje samotný princip DI a „znamená, že objekty, na kterých
objekt závisí, nejsou vytvářeny tímto objektem“, nýbrž je tato činnost přenechána objektům
jiným tzn., že „jsou tyto objekty získávány z vnějšího zdroje“ (Eini, 2006). Prostředkem
umožňujícím tento proces do určité míry zautomatizovat13 je právě DI kontejner, jehož
hlavní funkcí je obstarat vytváření instancí tříd „na jednom místě“. Toho je dosaženo často
automatickým sestavením stromu závislostí, které DI kontejner dokáže rozpoznat na základě
jeho vstupní konfigurace. (Kutišová, 2013)
Cílem srovnání frameworků v pokrytí této oblasti je:
a) obecné dodržování DI principu,
b) existence/podpora DI kontejneru (zdali jej framework obsahuje či nikoliv, v jaké po-
době a jaké možnosti konfigurace nabízí).
3.3.5 Komponentový vývoj
Hlavní myšlenkou komponentového vývoje je snaha o redukci stále se opakujícího se kódu
a znuvupoužitelnost určitých součástí aplikace, což ostatně koresponduje se smyslem frame-
worku. Proto je tento faktor zohledněn a v práci je porovnávána jeho inherentní podpora
ze strany frameworku. „Komponenty jsou relativně malé a nezávislé části určitého
systému.“ (Bose) Filosofie vychází z přesvědčení, že systém by měl být tvořen pokud možno
z existujících komponent, za účelem zrychlení vývoje a snížení nákladů.
V případě, že žádnou relevantní komponentu nelze použít, je nutné ji vytvořit a to buď vlast-
ními silami, či externě. Jelikož je jazyk PHP volně šiřitelný (tzv. open-source) a zároveň
13 Záleží na konkrétní implementaci DI kontejneru a případně na možnostech jazyka.
3 PHP frameworky 13
interpretovaný, mohou často vývojáři využít komponent vytvořených někým jiným a even-
tuálně si je za určitých podmínek přizpůsobit k použití ve vlastních projektech (záleží
na licenčních podmínkách, v zásadě je to ale technicky možné).
Z hlediska porovnání frameworků v této oblasti je cílem zjistit, zda obsahují předpřipravené
třídy, které umožní tvorbu znovupoužitelných komponent a zdali framework sám je sestaven
z relativně nahraditelných komponent.
3.3.6 Šablonový systém
PHP je ze své podstaty jazyk určený pro tvorbu šablon, vkládáním PHP kódu lze docílit
dynamicky generovaného HTML výstupu. Tento způsob14 - kombinace psaní „business
logiky“ a kódu pro vygenerování výstupu - je sice relativně snadný, na druhou stranu je však
ve většině případů nevhodný a dnes již může být považován za zastaralý. Klasický přístup
v zásadě nekoresponduje s rozdělením rolí v MVC architektuře, kde vrstva pohled je rela-
tivně izolována od vrstev ostatních a její zodpovědností je prezentace dat.
Ukazuje se však, že samotná separace sice přináší některé výhody, stále je však kodér nucen
psát čisté PHP, což znamená, že tvůrce šablony musí zároveň kromě značkovacích jazyků
(X)HTML znát i jazyk PHP, což sebou může přinést i některá bezpečností rizika. Navíc,
„míchání“ čistého PHP kódu a HTML, má za následek znepřehlednění obsahu šablony (ne-
týká se výstupu). Za účelem odstranění těchto a dalších nedokonalostí jazyka, případně jeho
rozšířením, vznikla řada speciálních šablonových systémů.
Smyslem šablonového systému je tedy odstínění kodéra od „nedokonalostí“ jazyka, zvýšení
bezpečnosti a v neposlední řadě zpřehlednění kódu šablony. Často je jejich implementace
koncipována jako rozšíření původního jazyka, přičemž výsledná syntaxe je napříč většinou
systémů prakticky totožná. Odhlédneme-li od faktu, že tvůrce šablon musí navzdory oddě-
lení od ostatních částí aplikace znát přinejmenším strukturu vstupních parametrů šablony,
stává se výsledný kód relativně přehlednějším a udržitelnějším.
Mezi typické znaky šablonového systému patří:
1. práce s proměnnými (deklarace, přiřazování hodnot, výpis, „escapování“15),
2. if konstrukce a cykly (s dodatečnými rozšířeními),
3. pomocné funkce (tzv. „helpery“),
4. vkládání/skládání/dědičnost šablon,
14 Dále označován jako „klasický“ způsob.
15 Jedná se o techniku nahrazování určitých znaků za znaky tzv. „bezpečné“, případně způ-
sob, jak předejít jejich chybné intepretaci.
3 PHP frameworky 14
5. podpora lokalizace.
Porovnání je realizováno s přihlédnutím k těmto vlastnostem, srovnány jsou i možnosti zá-
měny „nativního“ šablonového systému frameworku za jiný. Cílem porovnání je rovněž
identifikovat specifické rozdíly v možnostech šablonových jazyků.
3.3.7 Formuláře
Vývoj webových aplikací obnáší nejen generování určitého výstupu uživateli prostřednic-
tvím HTML na straně jedné, nýbrž nutně zahrnuje i problematiku zpracování dat získaných
od uživatele. Jedním z mechanismů, který vznikl z důvodu nutnosti data od uživatelů nejen
zobrazovat ale pochopitelně i získávat, jsou právě HTML formuláře. (Kosek, 1999)
V rámci srovnání možností generování HTML formulářů v jednotlivých frameworcích jsou
důležité následující aspekty:
1. Data, která chceme od uživatelů obdržet, mohou být různé povahy, resp. formátu.
2. Z důvodu konzistence a zajištění bezpečnosti je nutné data určitým způsobem vali-
dovat, přičemž složitost těchto validačních pravidel je odvislá od charakteru dat
a aplikační logiky, proto srovnání zahrnuje definici jak obvyklých pravidel tak i mož-
nost definice pravidel vlastních.
3. Charakterizován je způsob, jakým lze formuláře vytvářet a generovat výsledný
HTML kód (případně v souvislosti s používaným šablonovým systémem).
3.3.8 Session a Cookies
Prostředky session, resp. cookies slouží k překonání omezení protokolu HTTP, který je be-
zestavový tím, že onu „stavovost“ dokáží zajistit. (Shafik & Ramsey, 2007) V obecném
slova smyslu slouží cookies k ukládání stavových dat na straně klienta (angl. user agent),
přičemž jeho typickým představitelem je webový prohlížeč. Cookies se přenáší obousměrně,
k prvotnímu uložení, resp. odeslání cookie klientovi slouží HTTP hlavička Set-Cookie. Kli-
ent by tuto hlavičku měl umět zpracovat a následně při každém dalším požadavku spolu
s ostatními daty odesílat i právě tyto uložené cookies, které lze pak na straně serveru zpětně
zpracovat. (Internet Engineering Task Force, 2011)
Session se liší od cookies ve způsobu uložení stavových dat, která již nejsou ukládána
na straně klienta, nýbrž na straně serveru. Pro korektní spárování stavových dat s klientem
(např. uživatelem) je nutné zajistit přenos tzv. session ID, což je jednoznačný identifikátor
dané session, pomocí některého z dvou možných způsobů (The PHP Group, nedatováno):
Cookies – session ID je uloženo v samostatné cookie,
3 PHP frameworky 15
URL parametr – session ID se přenáší prostřednictvím URL jako hodnota speciál-
ního parametru.
Jazyk PHP podporuje přímou práci s daty uloženými jak v session, tak i cookies. Jelikož
potřeba zaznamenání a udržení určitých dat napříč několika HTTP požadavky vzniká velmi
často, je výhodné zvolit nějaký předem specifikovaný způsob pro práci s těmito daty (např.
za účelem odstínění vývojáře od nízko-úrovňových funkcí PHP, které se napříč různými
verzemi jazyka mohou potenciálně lišit).
Zásadní otázky pro srovnání frameworků jsou proto tyto:
1. Definuje framework nějaký unifikovaný způsob pro práci se session a cookies?
2. Liší se přístupy v práci se session/cookies v jednotlivých frameworcích? Případně
jak?
3.3.9 Databázová abstrakce
Pojem databáze lze v obecném měřítku definovat jako určitý uspořádaný soubor dat.
(Dictionary.com, nedatováno) V praxi se však tímto pojmem často míní některý z relačních
databázových16 systémů. V kontextu jazyka PHP se často jedná o volně šiřitelný systém
MySQL, ke kterému lze přistupovat pomocí nativních PHP funkcí. Existence celé řady dal-
ších alternativních databázových systémů (rovněž vycházejících z jazyka SQL), které mo-
hou zároveň mít svá jistá specifika, jsou jednou z příčin pro zavedení další vrstvy pro práci
s databází.
Smyslem databázové abstrakce je odstínění vývojáře od implementačně závislých vlastností
konkrétního databázového systému. Za předpokladu, že vývojář chce tvořit databázově re-
lativně nezávislou aplikaci, pak pravděpodobně bude zvažovat zavedení některé z abstrakč-
ních vrstev, které frameworky zpravidla poskytují. Databázová abstrakce by celkově mj.
měla přinést ulehčení práce vývojáři např. usnadněním zápisu databázových dotazů prostřed-
nictvím objektově orientovaného API. (Křižan, 2010)
Otázky pro porovnání:
1. Pro jaké databázové systémy existuje ze strany frameworku nativní podpora?
16 Dále se pod pojmem databázový systém míní databázový systém relační založený na ja-
zyku SQL.
3 PHP frameworky 16
2. Obsahuje vrstva databázové abstrakce kromě API souvisejícího s manipulací dat
(DML – Data Manipulation Language) tak i API pro popis/definici jejich struktury
(DDL – Data Definition Danguage)?
3. Je možné vykonané SQL příkazy logovat17?
Srovnání frameworků zahrnuje i hrubé otestování rychlosti databázové vrstvy, jehož zadání
je blíže popsáno na straně 21.
3.3.10 Autorizace, autentizace
Dalším problémem, se kterým je nutné se během vývoje webových aplikací určitým způso-
bem „vypořádat“, je otázka zabezpečení, neboli ověřování totožnosti uživatele (autenti-
zace) a řízení přístupu k různým částem aplikace (autorizace). Obě části spolu úzce
souvisí, protože v závislosti na autentizaci uživatele dochází zároveň k ověření, zdali je pří-
stup k danému zdroji18 autorizován. Stejně tak se lze setkat s modelovou situací, kdy je
uplatňován reverzní přístup - uživateli, který nemá dostatečná oprávnění (např. není přihlá-
šen), je nabídnuta možnost, jak dané oprávnění nabýt (např. přihlášením do systému).
Otázky pro srovnání:
1. Jaké možnosti framework z pohledu potřeby autorizace a autentizace uživatelů na-
bízí?
2. Obsahuje framework nějakou konkrétní implementaci pro řízení přístupu (známého
též pod zkratkou ACL - Access Control List)?
3. Na základě čeho je konkrétní uživatel (spojený s aktuální session) identifikován?
4. Je dobrým zvykem, že hesla uživatelů nejsou z bezpečnostních důvodů ukládána
ve své původní podobě, ale jako „zahešované“ (angl. hashed) řetězce znaků. Nabízí
framework nějaký vlastní sjednocený způsob hešování?
17 Viz kapitola 3.3.13.
18 Zdrojem se míní jakákoliv obecná součást aplikace (např. komponenta, stránka, apod.).
3 PHP frameworky 17
3.3.11 Lokalizace
Základem dobře navrženého frameworku umožňující jeho široké použití je jeho dostatečná19
obecnost. Mezi znaky široce použitelného frameworku lze zařadit podporu lokalizace, neboli
„proces překladu aplikačních zdrojů do lokalizovaných verzí pro každou z aplikačně
podporovaných kultur“ (Microsoft, 2014). V nejjednodušších případech se jedná pouze
o zajištění toho, že veškeré zprávy, které jsou (nebo mohou být) uživateli zobrazovány jsou
přeloženy do jednotlivých jazyků.
Bohužel, lokalizace v ideálním případě obnáší vyřešení několika specifických problémů da-
ných rozlišností světových kultur a jazyků. Jejich široká rozmanitost staví autory frame-
worku před poměrně složitý úkol, jehož cílem je to, aby výstup aplikace byl v souladu
s regionálními rozlišnostmi. Ukazuje se, že někdy je framework koncipován tak, že podpora
pro lokalizaci ve frameworku je, avšak jeho konkrétní implementace je ponechána na vývo-
jáři.
Otázky pro srovnání:
1. Disponuje framework zabudovanými lokalizačními prostředky?
2. Umožňuje framework definovat vlastní lokalizační prostředky?
3. Které součásti frameworku jsou „lokalizovatelné“?
3.3.12 Využití cache
Cache je „dočasné datové úložiště. Je to druh paměti, který představuje jednoduchý
a efektivní způsob jak zvýšit výkon webových aplikací – díky ukládání relativně statických
dat do cache a jejich načítání z cache, když jsou vyžadována, se šetří čas i výkon jinak nutný
k jejich opakovanému generování nebo získání z originálního úložiště“. (Křižan, 2010)
Použití cache zahrnuje transformační proces určitého kódu do takové podoby, pro kterou
platí předpoklad, že je efektivnější, než kód původní. Z pohledu přistoupení k využívání
cache nelze z určitostí říci, kdy se již cache „vyplatí“ a kdy ji lze považovat za „zbytečnou“.
Z pohledu PHP frameworků lze pak využít některých již implementačně zvládnutých řešení,
které byly vytvořeny za účelem usnadnění práce s cache a odstíněním vývojáře od konkrét-
ních vnitřních implementačních detailů cache (vývojář pracuje pouze s její API).
19 Vždy záleží na konkrétních požadavcích, zda lze framework považovat za dostatečně
obecný, tzn. případ od případu.
3 PHP frameworky 18
Otázky pro srovnání:
1. Nabízí framework možnost používat cache?
2. Umožňuje framework měnit/přidávat vlastní úložiště pro data v cache?
3. Jakým způsobem lze cache invalidovat (zneplatnit)?
3.3.13 Ladění a zpracování chyb
Princip a cíl procesu ladění lze charakterizovat jako snahu o odhalení existujících či poten-
ciálních chyb programu (v prostředí jazyka PHP je jím skript). Fakt, že PHP je jazyk inter-
pretovaný, může vést k relativně větší chybovosti (velkou mírou se na ní mohou podílet
zejména chyby formálního charakteru – překlepy apod.), protože veškeré chyby se mohou
projevit až za běhu skriptu. Proto je snahou frameworku proces ladění (angl. debugging)
vývojáři usnadnit a zefektivnit.
PHP obsahuje sadu vestavěných funkcí20, které slouží pro zpracování chyb (angl. errors)
a výjimek (angl. exceptions). Framework zpravidla vytváří nadstavbu nad těmito funkcemi
a přidává další přidanou hodnotu tím, že chybové stavy dokáže např. relativně přehledně
vizualizovat.
V souvislosti nejen s laděním, ale i praktickým provozem webových aplikací je velmi často
žádoucí zachycovat určité stavy (nemusí se jednat pouze o stavy chybové) zavedením tzv.
„logování“ (angl. logging), čímž je možné zachycovaná data zpětně analyzovat. (Lecky-
Thompson, Nowicki, & Myer, 2009) PHP opět nabízí nativní funkci pro jednoduchou práci
s chybovým logem21, jejíž použití ale nemusí z různých důvodů postačovat (např. nedosta-
tečná strukturovanost a nepřehlednost).
Otázky pro srovnání:
1. Jakým způsobem ve frameworku probíhá zpracování, resp. zachycení chybových
stavů (errors/exceptions)?
2. Obsahuje framework nějaký vizualizační nástroj určený k ladění?
3. Umožňuje framework nějaký druh nadstavbového logování?
20 http://cz2.php.net/manual/en/ref.errorfunc.php
21 Jedná se o vestavěnou funkci error_log (http://cz2.php.net/manual/en/function.error-
log.php).
3 PHP frameworky 19
3.3.14 Rychlost
Celkové zpracování požadavku
Objektivně porovnávat rychlost frameworku je obtížné, protože výsledky může ovlivnit
mnoho faktorů. Srovnání je provedeno na základě vytvoření jednoduché aplikace v každém
z frameworků. Její realizace je koncipována tak, aby verze vytvořená v jednom z nich (co se
týče funkcionality) byla ekvivalentní vůči ostatním.
Aplikace spočívá ve vytvoření tří stránek sloužících pro výpis jednoduché databáze knih:
1. Vytvoření domovské stránky obsahující odkaz na seznam knih.
2. Stránka se seznamem všech knih s možností zobrazit detaily.
3. Stránka s podrobnostmi o knize.
Modelová část aplikace je sdílená napříč všemi mutacemi aplikace. Jako zdroj databáze knih
slouží XML soubor Books.xml, který obsahuje celkem 5 knih (element //book/book). Pro zís-
kání kolekce všech knih či vyhledání jediné (dle jejího ID) je primárně určena fasáda22
JR\FrameworkComparison\Model\Facades\BookFacade.
V rámci srovnání bude pro každou stránku měřen celkový čas obsloužení skriptu (případné
nepodstatné části budou přeskočeny) a množství maximální alokované paměti. Výsledky
jsou přes pomocnou třídu JR\FrameworkComparison\Utils\Logger logovány do souboru
timelog.csv. Pro měření rychlosti bude použit nástroj
Nette\Diagnostics\Debugger::timer($name = NULL).
Měření bude provedeno dvojfázově:
1) „Caching fáze“ – slouží k odlišení vlivu použití cache, v rámci frameworku Nette je
abstrahováno od doby nutné k prvotní indexaci souborového systému (RobotLoader);
u frameworku Zend je tato fáze vynechána, protože se žádná cache nevyužívá;
2) „Cached fáze“ – v této fázi se předpokládá, že veškerá cache je již uložena a tudíž
by nemělo napříč měřeními docházet k významnějším časovým rozdílům.
Na každou stránku a fázi připadá celkem 10 měření (s výjimkou Zend, kde první fáze bude
vynechána), celkem tedy proběhne 50 měření. Výsledky v každé části jsou zprůměrovány
a následně interpretovány. Prostředí, ve kterém je měření prováděno, uvádí Tabulka 1.
22 Zjednodušující obalová třída pro práci s „nízko-úrovňovým“ nebo složitým API dalších
tříd a rozhraní, viz pojem Fasáda v terminologickém slovníku.
3 PHP frameworky 20
Ačkoliv Nette je možné provozovat i v jeho tzv. „minifikované“ verzi (veškerý zdrojový
kód je umístěn v jediném optimalizovaném PHP souboru), bude pro měření použito jeho
standardní distribuce.
Tabulka 1: Běhové prostředí pro porovnání frameworků (Zdroj: autor)
Parametr Hodnota
Verze PHP 5.4.25
Webový server Apache/2.4.7 (Win32)
Operační systém Windown 8.1 Pro
Procesor Intel(R) Core(TM) i5-4200U CPU @ 1.60GHz 2.29 GHz
Operační paměť 8.00 GB
Výkonnost PHP lze pozitivně ovlivnit nasazením tzv. akcelerátoru. Jedním z nich je rozší-
ření Zend OPcache, které zvyšuje rychlost PHP ukládáním předkompilovaného byte kódu
skriptů do sdílené paměti. To má v optimálním případě za následek zkrácení doby nutné
pro načtení jednotlivých skriptů odstraněním nutnosti jejich opětovné rekompilace při kaž-
dém požadavku. (The PHP Group, 2014)
Pro ověření výše uvedeného předpokladu bude sloužit další blok měření sestávající se do-
hromady z dalších 50 samostatných měření. Podmínky a způsob měření vycházejí z popisu
výše s tím rozdílem, že navíc bude aktivováno Zend OPcache rozšíření, jehož vstupní kon-
figuraci zachycuje následující tabulka (všechny ostatní parametry nabývají výchozích hod-
not).
3 PHP frameworky 21
Tabulka 2: Nastavení Zend OPcache rozšíření (Zdroj: autor)
Parametr Hodnota
Verze rozšíření opcache-7.0.3-5.4-ts-vc9-x8623
opcache.enable 1
opcache.memory_consumption 300
opcache.interned_strings_buffer 8
opcache.max_accelerated_files 8000
opcache.fast_shutdown 1
opcache.enable_cli 1
opcache.use_cwd 1
Přesný význam všech konfiguračních direktiv popisuje (The PHP Group, 2014).
Výkonnost databázové vrstvy
Pro srovnání rychlosti a paměťové náročnosti databázové vrstvy proběhne podobně jako
v předchozím případě sada měření, které jsou zaměřeny na zjištění výkonnosti:
1. Získání všech záznamů z tabulky,
2. Získání jednoho konkrétního záznamu z tabulky (na základě jeho ID).
Pro lepší vypovídací hodnotu bude měřen pouze čas související se samotným položením
dotazu a získáním výsledku. Zdrojovým databázovým systémem je MySQL, pro který exis-
tuje podpora ve všech třech frameworcích. Struktura dat (seznamu knih) odpovídá tabulce
book, jak je uvedeno ve výpisu 1. Rozlišen bude vliv akcelerátoru a způsob tvorby dotazu:
1. Manuální tvorba dotazu (zpravidla jediný příkaz, resp. metoda),
2. Postupné skládání dotazu (objektově orientovaný způsob konstrukce dotazu).
Pro účely měření výkonnosti 2. způsobu bude u frameworku Phalcon použito jeho „vysoko-
úrovňového“ jazyka PHQL. Důvodem je ověření, zda i přes jistou míru jeho specifičnosti24,
dosáhne lepších výsledků než Zend nebo Nette.
23 Dostupné z http://windows.php.net/downloads/pecl/releases/opcache/7.0.3/.
24 Tím, že daný dotazovací jazyk je již přímo propojen s určitým modelem a nelze jej použít
nezávisle na něm.
3 PHP frameworky 22
Výpis 1: Struktura zdrojové tabulky book (Zdroj: autor)
CREATE TABLE `book` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `author` varchar(255) NOT NULL, `date_published` date NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 INSERT INTO `book` (`id`, `name`, `author`, `date_published`) VALUES (1, 'Inferno', 'Dan Brown', '2013-05-14'), (2, 'A Game of Thrones', 'George R.R. Martin', '2003-01-01'), (3, 'World War Z', 'Max Brooks', '2006-09-12'), (4, 'Bad Monkey', 'Carl Hiaasen', '2013-06-11'), (5, 'Into the Wild', 'Jon Krakauer', '1997-01-20'), (6, 'My book', 'John Doe', '2014-05-08');
3.3.15 Ostatní
Mezi další vlastnosti, které lze u každého frameworku identifikovat a do jisté míry porovná-
vat, patří kromě faktorů technického charakteru rovněž řada socioekonomických, jako jsou:
licenční podmínky užití,
dokumentace,
komunita spojená s frameworkem,
existující rozšíření,
atd.
4 Porovnání PHP frameworků 23
4 Porovnání PHP frameworků Náplní následující části práce je porovnání konkrétních tří vybraných frameworků:
1) Zend Framework 2.3,
2) Nette 2.1.2,
3) Phalcon 1.3.1.
Cílem je nabídnout čtenáři celkový přehled o možnostech těchto frameworků za účelem
identifikace případných rozdílů ve způsobech jejich použití apod., přičemž popis vychází
z kritérií a otázek definovaných v předchozí části.
Výchozí předpoklady porovnání znázorňuje Tabulka 3.
Tabulka 3: Výchozí předpoklady pro porovnání frameworků (Zdroj: autor)
Zend Framework 225 Nette Phalcon
Verze 2.3 2.1.2 1.3.1
Oficiální webové
stránky
http://frame-
work.zend.com
http://nette.org/ http://phal-
conphp.com
4.1 Technické požadavky frameworku
4.1.1 Zend
Dle (Weier O'Phinney, 2014) nejsou explicitně požadovány žádné speciální požadavky, je-
diným výchozím požadavkem je stanovení minimální verze PHP 5.3.23, která musí být
na webovém serveru nainstalována.
4.1.2 Nette
Framework Nette vyžaduje minimální verzi PHP alespoň 5.3.1. Na rozdíl od ostatních fra-
meworků disponuje speciálním nástrojem „Requirements Checker“, který slouží ke kon-
trole splnění dalších specifických požadavků kladených frameworkem. Nástroj je součástí
standardní distribuce frameworku a jeho smyslem je ověření, že běhové prostředí serveru
25 Dále je již uváděn pouze zkrácený název Zend.
4 Porovnání PHP frameworků 24
splňuje všechny požadavky. Zároveň platí, že nesplnění některého z nich neznamená kom-
pletní nefunkčnost frameworku, nýbrž např. pouze určité části či rozšíření. Výstupem je ta-
bulkové zobrazení jednotlivých kritérií s případným rozšiřujícím popisem. (Nette
Foundation, 2014)
4.1.3 Phalcon
Framework Phalcon stejně jako Nette vyžaduje minimální verzi PHP 5.3.1. Distribuce fra-
meworku je realizována v porovnání s jinými frameworky jako rozšíření prostředí PHP for-
mou zvláštní knihovny. To znamená, že zdrojový kód je napsaný přímo v jazyce C, a proto
v zásadě existují dvě možnosti, jak balíček nainstalovat:
a) stažení zkompilovaného binární balíčku pro Windows,
b) stažení a následné zkompilování balíčku přímo pro konkrétní Linux distribuci.
Pro jeho následné zprovoznění je nutné balíček aktivovat patřičnou úpravou hlavního kon-
figuračního souboru PHP php.ini, která spočívá v přidání následujícího řádku (název kni-
hovny se může lišit v závislosti na platformě), viz Výpis 2.
Výpis 2: Aktivace Phalcon DDL rozšíření (Zdroj: (Phalcon Team and contributors, 2014))
extension=php_phalcon.dll
Na druhou stranu, přestože instalace v zásadě složitá není, faktické zprovoznění frameworku
obnáší změnu konfigurace PHP. Proto mohou být možnosti jeho reálného nasazení zásadním
způsobem omezeny, zejm. má-li dojít k jeho nasazení na některém ze sdílených webhostin-
gových prostředí, které nemá vývojář „přímo pod svoji kontrolou“.
4.2 Autoloading tříd
4.2.1 Zend
Zend obsahuje čtyři druhy autoloaderů (jmenný prostor Zend\Loader):
StandardAutoloader – vychází ze standardu PSR-0,
ClassMapAutoloader – předpokládá namapování tříd na patřičné zdrojové soubory,
pro zautomatizování lze využít speciální nástroj, který je součástí frameworku
a dokáže mapu vygenerovat procházením adresářové struktury (manuálně),
4 Porovnání PHP frameworků 25
ModuleAutoloader – určen pro nahrávání modulů (dokáže zpracovat i komprimované
archivy) (Zend Technologies Ltd., 2014),
PluginClassLoader – umožňuje tvorbu tzv. aliasů, čili zástupných názvů rozhraní
a tříd.
4.2.2 Nette
Nejdůležitější komponentou pro automatické nahrávání tříd, potažmo rozhraní je třída
Nette\Loades\RobotLoader. Framework rovněž obsahuje speciální autoloader
Nette\Loaders\NetteLoader, který jako zdroj interně používá pole s definicemi názvů tříd
a cest k příslušným zdrojovým souborům a primárně je určen pouze pro nahrávání frame-
workových komponent.
Princip fungování RobotLoaderu je originální, protože se chová podobně jako vyhledávací
robot (tzv. crawler), který rekurzivně prochází strukturu webu za účelem indexace obsahu.
RobotLoader obdobně prochází strukturu souborového systému a pro jakoukoliv nalezenou
třídu a rozhraní si „zapamatuje“ cestu ke zdrojovému souboru, ve kterém se daná deklarace
nachází. Pro svoji funkčnost RobotLoader vyžaduje specifikaci typu cache úložiště a regis-
traci daných adresářů, ve kterých se nalézají zdrojové soubory, které mají byt indexovány.
(Nette Foundation, 2014). Samozřejmě, že doba prvotního vybudování (adresáře se prochází
rekurzivně), resp. obnova cache je přímo úměrná množství a velikosti souborů, které musí
při indexaci analyzovat.
V případě potřeby lze RobotLoaderu indexaci určitých adresářů i zakázat, což může celko-
vou dobu analýzy v závislosti na konkrétních podmínkách značně zkrátit (zejména pokud se
jedná např. o produkty 3. stran, které mají již vlastní systém autoloadingu). RobotLoader
pro zajištění konzistence vyžaduje jednoznačnost deklarace tříd a rozhraní, pokud při inde-
xaci zjistí deklaraci již zaindexované třídy/rozhraní, vyvolá výjimku.
Výpis 3: RobotLoader - zakázání indexace adresáře (Zdroj: (Nette Foundation, 2014))
# soubor netterobots.txt # zakáže indexaci adresáře /Zend Disallow: /Zend
4.2.3 Phalcon
Autoloader Phalcon reprezentovaný třídou Phalcon\Loader sdružuje hned několik
autoloadingových strategií (seřazeno podle priority) (Phalcon Team and contributors, 2014):
4 Porovnání PHP frameworků 26
1. registrace tříd – nejvýřečnější metoda – každá třída má přiřazenu cestu ke zdrojo-
vému souboru,
2. registrace jmenných prostorů – obdoba PSR-0, ke jmenným prostorům jsou přiřa-
zeny adresáře (1:1), ve kterých se dané třídy, resp. rozhraní nachází,
3. registrace prefixů – obdoba předchozího způsobu s tím rozdílem, že názvy jmen-
ných prostorů jsou odděleny podtržítkem,
4. registrace adresářů – relativně nejnáročnější metoda, protože se daná třída/rozhraní
vyhledává postupně ve všech zaregistrovaných adresářích, zároveň se při prohledá-
vání nahraje první nalezený soubor.
4.3 MVC
4.3.1 Zend
Framework Zend obsahuje řadu rozhraní a tříd zastřešující proces zpracování požadavku
a vrácení odpovědi, které jsou umístěny ve jmenném prostoru Zend\Mvc. Pro obsloužení po-
žadavku slouží rozhraní Zend\Mvc\ApplicationInterface. Smyslem třídy implementující toto
rozhraní je zapouzdření vnitřní logiky životního cyklu aplikace a poskytnout tak vývojáři
možnost jejího přizpůsobení dle konkrétních požadavků.
Jelikož proces obsloužení lze relativně dobře zobecnit, poskytuje framework (stejně jako
frameworky ostatní) jeho základní implementaci, kterou představuje třída
Zend\Mvc\Application26. Třída z principu její interní logiky vyžaduje předání aplikační kon-
figurace a instanci třídy Zend\ServiceManager\ServiceManager, která je základní implemen-
tací návrhového vzoru service locator. Objekt typu service locator zajišťuje získávání
instancí dalších objektů, v tomto konkrétním případě však za cenu ztráty celkové
„průhlednosti“.
Reálné použití výchozí aplikační třídy (za určitých podmínek) tedy předpokládá implicitní
znalost vnitřní implementace, jelikož servisní třída musí poskytovat následující služby
(Introduction to the MVC Layer, 2014):
1. Zend\EventManager\EventManager – Zend je událostmi řízený („event driven”) frame-
work, z důležitých funkcí, která tato třída zajišťuje lze zmínit:
26 Dále jen jako tzv. aplikační třída.
4 Porovnání PHP frameworků 27
a. Připojování (metoda attach) a odpojování (metoda detach) tzv. posluchačů
(angl. listeners).
b. Spouštění událostí (metoda trigger), včetně možnosti definovat za jaké pod-
mínky lze událost vyvolávat (metoda triggerUntil).
2. Zend\ModuleManager\ModuleManager – jelikož Zend vychází z principu, že aplikace by
měla být složena ze samostatných modulů, definuje pro jejich inicializaci rozhraní
Zend\ModuleManager\ModuleManagerInterface, jehož základní implementaci předsta-
vuje právě tato třída,
3. Zend\Http\PhpEnvironment\Request – obalová třída příchozího HTTP požadavku,
4. Zend\Http\PhpEnvironment\Response – obalová třída pro HTTP odpověď aplikace.
Aplikační třída dále využívá řadu dalších pomocných komponent:
1. Zend\Mvc\RouteListener – zapouzdření tzv. „routovacího“ mechanismu, jehož úko-
lem je převedení HTTP požadavku na požadavek aplikační,
2. Zend\Mvc\DispatchListener – s využitím výstupu routování a dalších subkomponent
obaluje proces získání aplikačního požadavku a jeho obsloužení, tj. vrácení výstupu,
3. Zend\Mvc\View\ViewManager – komponenta zastřešující vrstvu pohled v MVC para-
digmatu (např. vytváření pohledu, registrace pomocných funkcí, apod.).
Z pohledu vývojáře je důležité, že tyto a další třídy zpravidla vždy implementují obecné
rozhraní stanovené frameworkem, čímž je dosaženo relativně širších možností, jak životní
cyklus v případě nutnosti upravit na základě specifických požadavků.
Způsobů, jak aplikační třídu použít, je v zásadě několik, v nejjednodušším případě spočívá
v zavolání statické metody Application::init, která provede inicializaci aplikace za použití
výchozích služeb, jak je znázorněno v následujícím výpisu:
Výpis 4: Ukázka nejjednodušší formy inicializace aplikační třídy Zend (Zdroj: (Zend
Technologies Ltd., 2014))
use Zend\Loader\AutoloaderFactory; use Zend\Mvc\Application; use Zend\Mvc\Service\ServiceManagerConfig; use Zend\ServiceManager\ServiceManager; // aktivace autoloaderu AutoloaderFactory::factory(); // získání konfigurace ze souboru $configuration = include 'config/application.config.php'; // inicializace a spuštění aplikace
4 Porovnání PHP frameworků 28
Application::init($configuration)->run();
Routování
„Routování reprezentuje akci párování HTTP požadavku na požadavek aplikační“ (Zend
Technologies Ltd., 2014), což prakticky vzato znamená, že dojde k analýze URI (Uniform
Resource Identifier) adresy a na základě stanovených kritérií či vzorů je možné určit cílový
řadič aplikace, který požadavek zpracuje.
Zend obsahuje dvě výchozí implementace aplikačního routeru (Zend Technologies Ltd.,
2014):
1. Zend\Mvc\Router\SimpleRouteStack,
2. Zend\Mvc\Router\Http\TreeRouteStack.
Obě třídy implementují rozhraní Zend\Mvc\Router\RouteInterface, které definuje jednak to-
vární metodu RouteInterface::factory pro vytváření instancí jednotlivých route, metodu
pro ověření zda předaný požadavek (objekt typu Zend\Stdlib\RequestInterface) odpovídá
pravidlům dané route (RouteInterface::match(Request $request)) a metodu pro zpětnou
konstrukci URI adresy (RouteInterface::assemble(array $params = array(), array
$options = array())).
Párování route probíhá standardně (na rozdíl od frameworku Nette) metodou LIFO (Last In
First Out), proto je korektního chování dosaženo postupnou registrací route obecných násle-
dovaných specifičtějšími, případně využitím nepovinného parametru pro stanovení priority
route (reprezentováno číselnou hodnotou, kde vyšší hodnota znamená vyšší prioritu).
Framework Zend je specifický tím, že rovněž obsahuje sadu několika speciálních HTTP
route umístěných ve jmenném prostoru Zend\Mvc\Router\Http. Jejich smyslem je poskytnout
vývojáři snadný způsob jak vytvářet routovací pravidla na základě určité vybrané části pro-
tokolu HTTP. (Zend Technologies Ltd., 2014)
Framework umožňuje definici route pro spouštění aplikace v příkazové řádce (konzoli),
která je oddělená od route klasických, nicméně konkrétní specifikace možných voleb a tvaru
route je upravena tak, aby bylo možné zadávat poměrně jasné a přitom stručné příkazy, jak
ukazuje (Zend Technologies Ltd., 2014).
Řadiče
Vrstva řadič architektury MVC je podporována ze strany frameworku za pomoci
Zend\Mvc\Controller\AbstractActionController. Z obecného hlediska framework považuje
za řadič jakoukoliv třídu, která implementuje rozhraní Zend\Stdlib\DispatchableInterface,
4 Porovnání PHP frameworků 29
které definuje jedinou metodu dispatch(Request $request, Response $response = null).
(Zend Technologies Ltd., 2014)
Pro usnadnění práce framework obsahuje další pomocné samostatné komponenty
(pluginy27), z nichž lze uvést několik příkladů (Zend Technologies Ltd., 2014):
Zend\Mvc\Controller\Plugin\Forward – umožňuje vyvolat akci jiného řadiče,
Zend\Mvc\Controller\Plugin\PostRedirectGet – přesměrování na danou URL či
akci,
Zend\Mvc\Controller\Plugin\Layout – umožňuje změnu výstupního rozvržení (angl.
layout) pohledu,
Zend\Mvc\Controller\Plugin\FlashMessenger – vytváření dočasně platných uživatel-
ských informačních zpráv, existují 4 možné typy zpráv, pro každou zprávu je defi-
nována zvláštní metoda.
Přidání uživatelsky definovaných pluginů je možné skrze konfiguraci aplikace. Vyvolání
funkcionality pluginu spočívá v zavolání metody AbstractController::plugin($pluginName,
array $options = null). Z důvodu zvýšení pohodlnosti je možné použít i zkrácený zápis,
protože třída implementuje magickou metodu __call, jak ukazuje Výpis 5. (Zend
Technologies Ltd., 2014)
Výpis 5: Možnost zkráceného zápisu volání služeb (Zdroj: autor)
// předpokládá volání uvnitř třídy řadiče $this->url();
4.3.2 Nette
Vývoj frameworku Nette se řídí několika obecnými principy, mezi nimiž je definování urči-
tých konvencí a jejich důsledné dodržování. Jejich znalost je ve výchozím stavu po vývojáři
dokonce vyžadována, což vede k relativně lepším návykům zkracující dobu vývoje a v ide-
álním případě i redukci chybovosti.
Obdobně jako framework Zend, Nette pro zapouzdření zpracování aplikační logiky používá
samostatnou třídu Nette\Application\Application28, která na rozdíl od frameworku Zend
neimplementuje žádné obecné rozhraní, nýbrž pouze dědí od základního společného předka
všech tříd frameworku Nette\Object. Díky tomu disponuje každá dědící třída schopností
27 Zásuvné moduly.
28 Dále uváděna pouze jako tzv. aplikační třída.
4 Porovnání PHP frameworků 30
definice veřejných událostí, které lze pak snadno vyvolávat, jak ukazuje Výpis 6. Jednodu-
chosti je dosaženo zavedením konvence pro pojmenování událostí a možnostmi jazyka PHP,
konkrétně existencí magické metody __call.
Výpis 6: Deklarace a vyvolání události ve frameworku Nette (Zdroj: autor)
use Nette\Object; class Foo extends Object { public $onBar = array(); public function raiseBar() { $this->onBar($this, ‘foo’); } } $foo = new Foo(); $foo->onBar = function (Foo $fooObject, $str) { echo $str; }; $foo->raiseBar(); // vypíše: // foo
Závislosti aplikační třídy se sice v principu příliš neliší od těch uvedených v souvislosti s fra-
meworkem Zend, poznamenat lze však fakt, že závislosti jsou definovány průhlednějším
způsobem, protože aplikace pro svůj chod vyžaduje 4 konkrétní typy objektů implementující
stanovená rozhraní a nespoléhá se na jejich implicitní existenci uvnitř service locatoru.
Routování
Pro účely podpory routování je zavedeno obecné rozhraní Nette\Application\IRouter, jenž
definuje metody pro:
1) mapování HTTP požadavku na aplikační požadavek –
IRouter::match(Nette\Http\IRequest $httpRequest),
2) konverzi aplikačního požadavku na URL – IRouter::constructUrl(Request
$appRequest, Nette\Http\Url $refUrl).
Kromě zmíněných metod jsou dále definovány dvě konstanty, jejichž existence akcentuje
schopnost frameworku rozlišovat speciální typy route (Nette Foundation, 2014):
4 Porovnání PHP frameworků 31
1) IRouter::ONE_WAY – routy označované tímto příznakem jsou jednosměrné v tom
smyslu, že aplikace provádí pouze mapování HTTP požadavku, nikoli však již re-
verzní generování URL,
2) IRouter::SECURED – slouží pro „vynucení“ používání zabezpečeného HTTPS proto-
kolu.
Framework kromě toho, že umožňuje zavedení vlastních uživatelsky definovaných routerů,
obsahuje rovněž několik základních implementací zmíněného rozhraní, jejich možnosti po-
užití se liší v závislosti na potřebách vývojáře a technických podmínkách, které jsou dány
provozním prostředím:
1. Nette\Application\Routers\SimpleRouter – nejjednodušší forma, která však neu-
možňuje generovat tzv. „cool“ adresy, na druhou stranu neklade žádné speciální po-
žadavky na cílové provozní prostředí,
2. Nette\Application\Routers\Route – pokročilá tvorba route, která umožňuje poměrně
přehledným způsobem definovat vstupní, resp. výstupní tvar URL adresy za použití
tzv. masek (např. výchozí hodnoty parametrů, validační výrazy, překlady, apod.);
na rozdíl od frameworku Zend lze masku za určitých podmínek definovat přehledně
a dostatečně konkrétně i bez nutnosti definovat každý parametr route zvlášť za po-
moci konfiguračního pole,
3. Nette\Application\Routers\RouteList – ve své podstatě nepředstavuje nic jiného,
než kolekci route Nette\Application\Routers\Route; v porovnání s frameworkem
Zend, jsou routy zpracovány FIFO (First In First Out) metodou,
4. Nette\Application\Routers\CliRouter – router pro zpracování požadavků (příkazů)
zadaných prostřednictvím příkazové řádky; dle (Nette Foundation, 2014) zatím ex-
perimentálního charakteru.
Řadiče
Architektura frameworku Nette vychází z modelu MVP, který je obdobou modelu MVC.
Pojem řadič je nahrazen pojmem presenter a jeho význam je dle (Frank, 2013) modifikovaný
tak, že oproti řadiči obstarává kromě aplikační i logiku prezentační. Pro zjednodušení je
presenter dále chápán jako ekvivalent řadiče. Z pohledu frameworku lze za řadič, resp. pre-
senter označit jakoukoliv třídu vycházející (dědící) z abstraktní třídy
Nette\Application\UI\Presenter (přesněji řečeno třídu implementující rozhraní
Nette\Application\IPresenter). (Nette Foundation, 2014)
Funkci presenteru lze demonstrovat znázorněním jeho životního cyklu, viz Obrázek 1.
4 Porovnání PHP frameworků 32
Obrázek 1:
Životní cyklus Nette presenteru (Zdroj: (Nette Foundation, 2014))
Životní cyklus Presenteru (Nette Foundation, 2014):
1. startup() – metoda sloužící k inicializaci Presenteru, při jejím přepsání je vyžado-
váno zavolání její rodičovské verze,
2. action<NázevAkce>(…) – slouží k oddělení doménové logiky od vykreslovací části,
umožňuje např. přesměrování na jinou akci,
3. handle<NázevSignálu>(…) – obslužné metody pro tzv. signály; signál představuje
„komunikaci se serverem pod prahem normálního pohledu, tedy akce, které se dějí,
aniž by se změnil pohled“ (Nette Foundation, 2014),
4. beforeRender() – metoda volaná těsně před vykreslením vhodná např. pro úpravu
šablony pro více pohledů současně,
5. render<NázevAkce>(…) – metoda sloužící k úpravě pohledu, za jinak nezměněných
okolností dojde k vykreslení automaticky a proto v této fázi nejčastěji dochází pouze
k předání proměnných šabloně,
4 Porovnání PHP frameworků 33
6. afterRender() – metoda volaná před konečným vykreslením pohledu – odesláním
aplikační odpovědi v textové podobě (chybí na obrázku),
7. shutdown($response) – ukončení běhu Presenteru.
Presenter obsahuje řadu pomocných metod, které slouží např. k přesměrování, vyvolání chy-
bového stavu, zasílání bleskových zpráv (angl. flash messages), aj. Na rozdíl od frameworku
Zend však tato funkcionalita není dána samostatnými pluginy, nýbrž jsou součástí API pre-
senteru. Požadované chování lze proto upravit jedině přepsáním konkrétní metody v dědící
třídě.
V rámci rozvoje frameworku, převládá poměrně značná tendence upouštět od používání
service locatoru, což se projevuje i tím, že další nutné služby, které presenter potřebuje
ke svému chodu, jsou mu transparentně předány v metodě Presenter::injectPrimary(…).
(Nette Foundation, 2014)
4.3.3 Phalcon
Základním kamenem MVC modelu ve frameworku Phalcon je aplikační třída
Phalcon\Mvc\Application, která „zapouzdřuje veškeré komplexní operace související
s vytvářením instancí všech potřebných komponent“ (Phalcon Team and contributors, 2014).
Toto tvrzení může vzbudit mylný dojem, že se v jedná o DI kontejner. Z hlediska třídní
hierarchie se jedná o potomka třídy Phalcon\DI\Injectable, což již naznačuje, že aplikační
třída je naopak speciální třídou, které lze vkládat/předávat vnější závislosti za pomoci me-
tody Phalcon\DI\InjectionAwareInterface::setDI(Phalcon\DiInterface
$dependencyInjector).
Z pohledu praktického použití jsou důležité následující metody:
1. Application::handle(string $uri = null) – metoda pro obsloužení příchozího po-
žadavku, která je obdobou metody Nette\Application\Application::run(), avšak
na rozdíl od ní, metoda vrací specifickou odpověď (instanci třídy) typu
Phalcon\Http\ResponseInterface; hodnotu takto získanou lze následně jednoduše
předat na standardní výstup,
2. Application::registerModules($modules, $merge = null) – funguje jako registrátor
modulů aplikace; framework tedy očekává jejich manuální registraci.
Routování
Stejně jako ostatní frameworky, Phalcon podporuje standardní proces routování za pomoci
rozhraní Phalcon\Mvc\RouterInterface. Zodpovědnost za správnou registraci jednotlivých
route je ponechána právě jemu a jeho výchozí implementací je třída Phalcon\Mvc\Router.
Routy jsou složeny z masek/vzorů, regulárních výrazů apod., jejichž zápis se nikterak příliš
4 Porovnání PHP frameworků 34
neliší např. od frameworku Nette. Pro speciální případy užití umožňuje rozhraní kromě ji-
ného také omezit vstupní HTTP metodu na některou z hodnot definovaných tímto protoko-
lem, jak ukazuje dokumentační příklad (Phalcon Team and contributors, 2014).
Framework disponuje speciálním typem routeru Phalcon\Mvc\Router\Annotations, který
umožňuje definici tvaru route přímo v konkrétních třídách řadičů prostřednictvím tzv. ano-
tačních komentářů. Jedná se o vlastnost ojedinělou napříč porovnávanými frameworky, byť
ve výsledku může za určitých podmínek vést k paradoxnímu znepřehlednění aplikace29, pro-
tože routy již nejsou definovány na jednom místě, ale napříč několika soubory.
Řadiče
Vytváření instancí a volání příslušných akcí (angl. dispatching) provádí třída
Phalcon\Mvc\Dispatcher. Celý proces je cyklického charakteru a založený na událostech,
přičemž některé události jsou „zastavitelné“30. Zděděním třídy Phalcon\Mvc\Controller do-
jde k deklaraci nového řadiče a pro zpracování akcí jsou definovány příslušné metody, při-
čemž platí, že každá akce musí mít definovánu svoji metodu (rozdíl oproti Nette, kde metoda
reprezentující určitou akci nutně deklarována být nemusí). Názvy obslužných metod ve vý-
chozím stavu musí reflektovat stejnou konvenci jako v případě frameworku Zend, jak uka-
zuje Výpis 7.
Výpis 7: Konvence pro pojmenování akce řadiče (Zdroj: autor)
// <name> … název akce public function <name>Action() { … }
Z hierarchického hlediska je třída řadiče potomkem stejné třídy jako třída aplikační, čímž je
zajištěn jednotný způsob předávání externích závislostí prostřednictvím již zmíněné metody
InjectionAwareInterface::setDI($dependencyInjector). Používání této metody je však
svým způsobem rezignací na princip DI, protože třídě jsou takto předány ve skutečnosti
i závislosti, které vůbec nepotřebuje.
Veškerá dodatečná funkcionalita týkající se např. přesměrovávání, zasílání bleskových
zpráv apod., je realizována prostřednictvím příslušných rozšíření, které lze v rámci zjedno-
dušení (obdobně jako ve frameworku Zend) volat přímo uvnitř řadiče způsobem, který na-
stiňuje Výpis 8.
29 Záleží na rozsahu aplikace, na stanovení a dodržení konvencí apod.
30 To znamená, že pokud jakýkoliv posluchač (obslužná metoda) vrátí hodnotu false, dojde
k ukončení činnosti.
4 Porovnání PHP frameworků 35
Výpis 8: Zkrácený způsob volání rozšíření uvnitř řadiče (Zdroj: autor)
public function indexAction() { // <nazevRozsireni> … platný název zaregistrovaného rozšíření $this-><nazevRozsireni>(…); }
Více informací ohledně registrace rozšíření, resp. DI (netýká se pouze frameworku Phalcon)
je podáno v následující kapitole.
4.4 DI (Dependency Injection)
4.4.1 Zend
Důsledné dodržování principů DI je v určitých případech obtížné (např. špatný architekto-
nický návrh), někdy dokonce nemusí být z důvodu zjednodušení požadováno. Výsledkem
však může být horší testovatelnost a snížení průhlednosti rozhraní, resp. tříd. Příkladem bu-
diž aplikační třída Zend\Mvc\Application, která vyžaduje předání instance třídy
Zend\ServiceManager\ServiceManager (service locator). Otázkou zůstává, zdali je toto zjed-
nodušení v tomto případě skutečně nutné31.
Framework obsahuje robustní implementaci vlastního DI kontejneru, jenž je reprezentován
třídou Zend\Di\Di. Základního požadavku na funkcionalitu DI kontejneru – vytváření in-
stancí tříd – je dosaženo definicí metody Di::newInstance($name, array $params = array(),
$isShared = TRUE). Zavoláním této metody dojde k vytvoření nové instance požadované
třídy, přičemž hodnoty parametrů požadovaných konstruktorem třídy lze určit v druhém pa-
rametru. Třetí parametr určuje, zda je možné vytvořenou instanci opětovně použít při zavo-
lání metody Di::get($name, array $params = array()), která v případě, že instance
požadované třídy s danými parametry byla již vytvořena, vrací právě tuto existující instanci.
Kontejner v nejjednodušším případě nevyžaduje žádnou specifickou konfiguraci. Pro správu
vzájemných závislostí tříd a porozumění struktuře tříd, které má kontejner spravovat, slouží
tzv. definiční seznam (třída Zend\Di\DefinitionList). Definiční seznam je v principu pou-
hou obálkou pro pole definicí, které jsou dány polem instancí tříd implementujících rozhraní
Zend\Di\Definition\DefinitionInterface. Framework obsahuje několik základních druhů
definic (všechny se nacházejí ve jmenném prostoru Zend\Di\Definition):
1. ArrayDefinition – nejjednodušší explicitní způsob popisu struktury,
31 Díky tomu, že lze nahlédnout do implementačních detailů třídy.
4 Porovnání PHP frameworků 36
2. RuntimeDefinition – výchozí definice pro definiční seznam, který strukturu zjišťuje
za běhu skriptu,
3. CompilerDefinition – podobný princip jako u RuntimeDefinition, s tím rozdílem, že
za běhu zjištěná „zkompilovaná“ struktura tříd může být uložena na disk pro pozdější
použití a tím odpadá proces introspekce při každém běhu skriptu (Zend Technologies
Ltd., 2014),
4. BuilderDefinition – umožňuje překonat problém se vkládáním závislostí v přípa-
dech, kdy nelze použít tzv. type hinting tím, že jsou pro tyto případy programově
definována zvláštní pravidla (Zend Technologies Ltd., 2014),
5. ClassDefinition – definice struktury pouze pro konkrétní třídu.
DI kontejner a řadiče
Ačkoliv se to může zdát překvapivé, Zend v rámci řadičů DI kontejner ve výchozím stavu
vůbec nepoužívá. Naopak se spoléhá na existenci service locatoru v podobě třídy
Zend\ServiceManager\ServiceManager. Vkládání závislostí do řadičů a dostání tak principu
DI lze realizovat např. konfigurací, jak ukazuje Výpis 9 (modifikovaný příklad převzat
z (Sluiman, 2012)).
Výpis 9: Příklad předání externí závislosti řadiči za pomocí setter injection (Zdroj: (Sluiman,
2012))
///////////////////////// // soubor s řadičem namespace MyModule\Controller; class FooController extens Zend\Mvc\Controller\AbstractActionController { private $myService; public function setMyService($myService) { $this->myService = $myService; } } ///////////////////////// // soubor s konfigurací use MyModule\Controller; // konfigurace return array(
'controllers' => array( 'factories' => array(
4 Porovnání PHP frameworků 37
'MyModule\Controller\Foo' => function($serviceManager) { $controller = new Controller\FooController;
$myService = $serviceManager->getServiceLocator() ->get('myService');
$controller->setMyService($myService);
return $controller; },
), ),
);
Z příkladu je patrné, že v případě, kdy nechceme uvnitř řadiče používat service locator, jsme
„nuceni“ používat poměrně „krkolomného“ způsobu předávání závislostí. Neexistuje tedy
žádný frameworkem automatizovaný proces vkládání externích závislostí přímo do řadiče
(myšleno transparentním způsobem v duchu DI) a řešení tohoto problému je ponecháno
na vývojáři.
4.4.2 Nette
Srovnáme-li definici závislostí aplikačních tříd pro framework Zend a Nette, druhá ze jme-
novaných deklaruje výčet závislostí nikoliv pomocí obecného service locatoru, nýbrž po-
mocí jasně specifikovaných parametrů. Předpoklad, že aplikační třída Nette neobsahuje
žádné skryté závislosti, lze snadno ověřit nahlédnutím do kódu příslušné třídy.
Univerzální DI kontejner představuje třída Nette\DI\Container, který umožňuje veškeré zá-
kladní operace spojené se správou služeb (přidávání, odebírání, ověřování existence). O se-
stavení („zkompilování“) kontejneru se stará třída Nette\DI\Compiler, která pracuje s tzv.
rozšířeními (angl. extensions). Framework obsahuje několik typů těchto rozšíření umístě-
ných ve jmenném prostoru Nette\DI\Extensions:
1. NetteExtension – obsahuje sadu základních služeb frameworku,
2. PhpExtension – rozšíření umožňující nastavení tzv. PHP direktiv,
3. ConstantsExtension – speciální typ rozšíření pro definici PHP konstant,
4. ExtensionsExtension – umožňuje registraci dalších rozšíření v konfiguračním sou-
boru.
Silnou vlastností Nette DI kontejneru je to, že disponuje tzv. auto-wiringem – automatickým
mechanismem rozpoznání závislostí konstruktorů tříd na základě jejich signatury. Nutnost
explicitně definovat hodnoty parametrů je tak omezena na minimum (v závislosti na složi-
tosti a explicitnosti – vyžaduje tzv. type hinting).
4 Porovnání PHP frameworků 38
DI kontejner je velmi úzce spjat s konfigurací samotného frameworku, resp. aplikace
a na rozdíl od frameworku Zend se vyznačuje tím, že konfiguraci lze kromě běžného způ-
sobu definice přímo pomocí kódu psaného v PHP (konfigurační pole) provádět pomocí
zvláštního konfiguračního souboru ve formátu NEON32, který tak činí konfiguraci relativně
úspornější, co do množství textu nutného k zápisu a může tak přispět k přehlednosti (např.
v porovnání se zmíněným způsobem zápisu pomocí konfiguračního pole či XML atp.).
Ve skutečnosti překonává některé nevýhody ostatních způsobů (INI – neumožňuje zanořo-
vání, XML – je poměrně nepřehledné a nutí psát více textu, než by bylo bezpodmínečně
nutné, PHP – nejefektivnější způsob zápisu, ale zároveň relativně náchylný k chybám v pří-
padě většího množství kódu).
DI kontejner a řadiče33
Pro přímý přístup k DI kontejneru uvnitř řadiče je sice z historických důvodů možné použít
metody Presenter::getContext(), což lze považovat za určitý ekvivalent metody
AbstractController::getServiceLocator() v frameworku Zend, v současnosti se ale již
jedná o zavržený (angl. deprecated) přístup. Momentálně jsou ze strany frameworku podpo-
rovány dva způsoby předávání závislostí dovnitř řadiče:
1) property injection – vyžaduje použití anotačního komentáře @inject a zároveň musí
být tyto vlastnosti definovány jako veřejné (angl. public),
2) method injection – definice speciálních jednoúčelových metod, jejichž název musí
splňovat danou konvenci (inject<NazevSluzby>) které jsou volány výchozí továrnou
(angl. factory) řadičů (třída Nette\Application\PresenterFactory).
Následující Výpis 10 demonstruje praktické použití obou způsobů:
Výpis 10: Příklad dvou způsobů předání externích závislostí presenteru za pomoci property
a method injection (Zdroj: autor)
// předpokládá se existence třídy MyNamespace\Foo a její registrace // v rámci konfigurace služeb DI kontejneru namespace MyNamespace; // property injection class MyPresenter extends Nette\Application\UI\Presenter { /** * @inject
32 http://ne-on.org
33 V souvislosti s frameworkem Nette je význam označení Presenter ztotožněn s pojmem
řadič.
4 Porovnání PHP frameworků 39
* @var MyNamespace\Foo */ public $foo; } // method injection class MyPresenter extends Nette\Application\UI\Presenter { private $foo; public function injectFoo(Foo $foo) { // jelikož se jedná o jednoúčelovou metodu, pro zajištění konzistence
// je vhodné přidat podmínku zamezující přepsání // již existující instance (vyvolání výjimky)
$this->foo = $foo; } }
4.4.3 Phalcon
Opět, uvedeme-li způsob, jakým jsou předány vnější závislosti do aplikační třídy frame-
worku Phalcon, zjistíme, že se prakticky příliš neliší od aplikační třídy Zend, jelikož v kon-
struktoru vyžaduje celý DI kontejner. S podivem lze pak porozumět dokumentačním
komentářům34, které deklarují, že jednotlivé komponenty frameworku jsou navzájem rela-
tivně oddělené (ukazuje se, že nic není dokonalé).
Byť je kontejner v obecné rovině reprezentován třídou Phalcon\DI, v praktické rovině vyža-
dující co největší míru zjednodušení (tudíž nutnost psát méně kódu při zachování požado-
vané funkčnosti) je možné použít třídu typu Phalcon\DI\FactoryDefault, která se o registraci
základních služeb postará automaticky.
Kromě základních metod pro přidávání, odebírání, či ověřování existence určitých služeb,
DI kontejner např. umožňuje za běhu za určitých podmínek35 změnu třídy, kterou služba
reprezentuje či dodatečnou změnu parametrů (Phalcon Team and contributors, 2014) (bez
toho, aby bylo nutné službu nejprve odebrat a následně opětovně přidat s novými parametry).
Z dalších zvláštností (v porovnání s ostatními frameworky) lze uvést:
34 http://docs.phalconphp.com/en/latest/reference/di.html#our-approach
35 Záleží na zvoleném způsobu registrace služby.
4 Porovnání PHP frameworků 40
1) DI kontejner lze použít k vytváření instancí tříd, i když tyto třídy nejsou v kontejneru
zaregistrovány (při nenalezení služby s daným názvem se framework pokusí nalézt
třídu s tímto názvem a vytvořit její instanci),
2) Pokud třída zastoupená službou implementuje rozhraní
Phalcon\DI\InjectionAwareInterface, DI kontejner této třídě automaticky předá in-
stanci sebe sama za pomocí metody
InjectionAwareInterface::setDI(Phalcon\DiInterface $dependencyInjector);
vlastnost zmiňuji v reakci na již zmíněné prohlášení autorů o volné provázanosti fra-
meworkových komponent a ačkoliv může v jistých případech být užitečná, jedná se
o popření principu DI,
3) Existence statické metody Phalcon\DI::getDefault(), která je součástí dokumentace
DI36 opět vede k otázce, do jaké míry to s DI myslí autoři frameworku vážně (možná
implicitně předpokládají, že případný čtenář si je vědom potenciálních problémů
s tím spojených).
Konfigurace kontejneru je (přinejmenším v porovnání s frameworkem Nette) z pohledu
„pohodlnosti“ relativně náročná, protože kontejner nedisponuje žádným mechanismem
pro automatické rozpoznání a přenášení externích závislostí napříč objektovým grafem.
DI kontejner a řadiče
Přístup k DI kontejneru uvnitř řadiče, který je potomkem třídy Phalcon\DI\Injectable je
prakticky stejný jako ve frameworku Zend, díky existenci metody Injectable::getDI().
Žádný automatizovaný způsob jak předat řadiči externí závislostí, který by zároveň reflek-
toval DI přístup, Phalcon nenabízí.
4.5 Komponentový vývoj
4.5.1 Zend
Jednotlivé části, resp. třídy frameworku lze považovat za relativně samostatné a znovupou-
žitelné komponenty. Poměrně hojně je používáno abstraktních rozhraní, čímž je dosaženo
relativní nahraditelnosti jednotlivých komponent jednak komponentami nacházejícími se již
ve frameworku samotném, ale i těmi z 3. stran.
36 http://docs.phalconphp.com/en/latest/reference/di.html#accessing-the-di-in-a-static-way
4 Porovnání PHP frameworků 41
Framework je rozdělen do logických součástí, jejichž distribuce je realizována v zásadě
dvěma způsoby:
1) 1 balíček obsahující všechny součásti standardní distribuce,
2) každá logická část distribuována zvlášť odděleně od ostatních (pomocí nástroje
Composer)37.
Výhodnou druhého způsobu je především to, že specifickou část frameworku lze použít sa-
mostatně a v případě, že daný balíček přeci jen vyžaduje další externí komponenty, dokáže
tyto závislosti Composer sám rozpoznat (pomocí konfiguračního souboru composer.json,
který je umístěn v balíčku) a v případě nutnosti dodatečně komponenty automaticky získat.
Na druhou stranu, hovoříme-li o komponentách a jejich rozdělení na komponenty:
1) vykreslitelné,
2) nevykreslitelné,
framework Zend prakticky nepředstavuje žádné abstraktní pojetí pro oba typy. Architektura
není hierarchického charakteru a nelze vypozorovat žádný přímý logický vztah typu rodič-
potomek.
4.5.2 Nette
Podobně jako Zend, je framework Nette složen z logických částí, liší se však především
celkovým množstvím komponent. U tvůrců frameworku Nette převládá relativní střídmost
v pohledu na to, co vše by měl framework nabízet nativně a které oblasti již ponechat uživa-
telům. Proto framework poskytuje způsob, jak tuto rozšiřitelnost zajistit pomocí definice
abstraktních rozhraní. V porovnání s frameworkem Zend se může zdát, že programování
proti rozhraní je v Nette použito paradoxně v menším rozsahu. Tento dojem je ovlivněn
celkově menším počtem komponent a odlišnou filosofií frameworku.
Framework však představuje vlastní originální pojetí pro komponentový vývoj aplikací, je-
likož explicitně rozlišuje vykreslitelné a nevykreslitelné komponenty aplikace a zavádí
obecný hierarchický stromový model pro tvorbu a skládání jednotlivých komponent dohro-
mady v jeden celek. Strukturu komponentového modelu znázorňuje Výpis 11.
Výpis 11: Komponentový model frameworku Nette (Zdroj: (Nette Foundation, 2014))
Nette\Object | +- Nette\ComponentModel\Component { IComponent } |
37 Kompletní seznam balíčků je k dispozici na adrese https://packages.zendframework.com.
4 Porovnání PHP frameworků 42
+- Nette\ComponentModel\Container { IContainer } | +- Nette\Application\UI\PresenterComponent { ISignalReceiver, IStatePersistent } | +- Nette\Application\UI\Control { IPartiallyRenderable } | +- Nette\Application\UI\Presenter { IPresenter }
Ultimátním předkem všech tříd frameworku je třída Nette\Object. Děděním od této třídy do-
chází k určité standardizaci chování všech objektů frameworku, protože odstraňuje některé
nedostatky jazyka PHP a zároveň přináší některé užitečné vlastnosti (Nette Foundation,
2014):
1) Třídy jsou tzv. striktní - v případě odkazování se na neexistující třídní proměnnou
dojde k vyvolání výjimky,
2) Definice vlastností třídy za pomocí tzv. getterů a setterů – doplňuje možnost de-
finice vlastností známých např. z jazyka C#, kdy se lze odkazovat na třídní vlastnost
přímo pomocí jejího názvu i přesto, že viditelnost vnitřní proměnné reprezentující
tuto vlastnost by tento přístup neumožňovala,
3) Události – na rozdíl od ostatních frameworků jsou události vyvolávány přímo
na konkrétních objektech, nikoliv za pomoci externího „správce událostí“; realizo-
váno definicí veřejné třídní proměnné s patřičným názvem, který musí splňovat kon-
venci (např. public $on<NazevUdalosti> = array();),
4) Rozšiřující metody (angl. extension methods) – umožňují za běhu přidávat do exis-
tující třídy další veřejné metody,
5) Reflexe a anotace – vzájemně spolu souvisí, neboť za pomoci reflexe (získání for-
málních informací o třídě) lze jednoduše získat např. seznam všech anotací (speciální
způsob zápisů dokumentačního komentáře) dané třídy, metody či proměnné.
Obecnými potomky Nette\Object jsou dle diagramu následující třídy:
Nette\ComponentModel\Component – zajišťuje, že každá komponenta má definován
svůj název (z pohledu hierarchie komponent) a může či nemusí být potomkem kom-
ponenty jiné, resp. kontejneru,
Nette\ComponentModel\Container – komponenta, která umožňuje samotnou tvorbu
hierarchie, neboť obsahuje metody pro dynamickou správu svých potomků,
Nette\Application\UI\PresenterComponent – speciální typ komponenty předurčující
její použití v rámci presenteru; tyto komponenty umožňují např. uchovávání svého
stavu prostřednictvím URL a zpracovávání signálů,
4 Porovnání PHP frameworků 43
Nette\Application\UI\Control – vykreslitelná komponenta, poměrně silný prvek
frameworku, protože umožňuje sestavení aplikace z různých především uživatelsky
definovaných částí, přičemž způsob vykreslení lze ovlivnit např. pouhou změnou ša-
blon,
Nette\Application\UI\Presenter – z diagramu je patrné, že Presenter v podání fra-
meworku Nette není nic jiného, než speciální typ vykreslitelné komponenty, který
navíc dokáže zpracovat aplikační požadavek a způsob jeho zpracování je dán jeho
životním cyklem.
Framework je sice distribuován mj. i jako balíček pro Composer, nicméně pouze jako celek.
Žádostem o rozdělení frameworku na samostatné balíčky bylo prakticky vyhověno až
ve verzi 2.2 beta138.
4.5.3 Phalcon
Komponenty frameworku Phalcon jsou rozděleny stejně jako u obou předchozích frame-
worků do příslušných jmenných prostorů, ale narazit lze opět na paradox spojený s DI
a programováním proti rozhraní. Velká část tříd implementuje alespoň jedno obecné roz-
hraní, často se jedná o Phalcon\Events\EventsAwareInterface pomocí, kterého lze zařídit po-
slouchání událostí, či rozhraní Phalcon\DI\InjectionAwareInterface, které však navzdory
názvu znamená, že je třídě možné předat celý DI kontejner, resp. service locator a nikoliv
závislosti přesně specifikované.
Budeme-li chtít nalézt jakousi paralelu s ohledem na zavedení abstraktní třídy reprezentující
(ne)vykreslitelnou komponentu, pak se jejímu účelu nejvíce podobá třída
Phalcon\Mvc\User\Component a to i přesto, že nedefinuje žádné podobné metody a ani nedis-
ponuje jejími vlastnostmi. Prakticky se pouze jedná o co do funkčnosti prázdnou třídu, která
má však k dispozici přímý přístup k řadě služeb poskytovaných frameworkem, které jsou
de facto sdílené napříč celou aplikací, což přináší výhody (z pohledu pohodlnosti vývojáře),
avšak i jednu zásadní nevýhodu - třída je závislá na celém DI kontejneru, jehož obsah je
relativně „neznámý a nestálý“, protože služby mohou být registrovány a odebírány dyna-
micky a komponenta se stává relativně hůře testovatelnou.
Možnosti distribuce frameworku coby soustavy samostatných balíčků je omezena faktem,
že se jedná o framework kompilovaný z jazyka C, tudíž pro použití byť jen určité kompo-
nenty je nutné „sáhnout“ po celém rozšíření.
38 http://forum.nette.org/en/1464-nette-framework-2-2-beta1-released
4 Porovnání PHP frameworků 44
4.6 Šablonový systém
4.6.1 Zend
Šablonový systém frameworku Zend se skládá z několika vrstev (Zend Technologies Ltd.,
2014) z nichž základní je Zend\View\View, která obsahuje definici tzv. strategií pro mapování
aplikačního požadavku na výstup pohledu. Tyto strategie jsou dvojího typu:
1. Vykreslovací strategie (angl. rendering strategies) – na základě požadavku určují,
jaký vykreslovač (angl. renderer) bude použit,
2. Strategie odpovědi (angl. response strategies) – určují podobu konečné odpovědi.
Definicí vlastních strategií lze ovlivnit chování aplikace, co se týče jejího výstupu např.
pro každý modul zvlášť.
Framework je specifický tím, že sám o sobě pro kódování šablon nenabízí vlastní šablono-
vací jazyk, tak jak je to běžné u jiných frameworků, nýbrž ve výchozím stavu nabízí
tzv. „PHP vykreslovač“ (třída Zend\View\Renderer\PhpRenderer), jehož elementární vlast-
ností je to, že kód šablon je psán přímo v jazyce PHP, viz Výpis 12, proto je kód interpreto-
ván „tak jak je“. Jedná se poměrně o efektivní způsob tvorby šablon, co se týče výkonosti
(za cenu zhoršení srozumitelnosti celkového kódu).
Výpis 12: Ukázka šablony psané pro PhpRenderer (Zdroj: autor)
// soubor s šablonou <h1>Rows</h1> <?php if (count($this->rows) == 0): ?> <p>No rows…</p> <?php else: ?>
<ul> <?php foreach ($this->rows as $row): ?> <li> <?php echo $this->escapeHtml($row->name); ?> </li> <?php endforeach; ?> </ul> <?php endif; ?>
Kromě PHP vykreslovače obsahuje framework i dva další:
Zend\View\Renderer\JsonRenderer – generování odpovědi ve formátu JSON,
Zend\View\Renderer\FeedRenderer – generování RSS feedu.
4 Porovnání PHP frameworků 45
Pro ukládání, resp. registraci proměnných šablonám slouží prvek typu
Zend\View\Model\ViewModel (pohledový model), který je obálkou pro tzv. kontejnery pro-
měnných (angl. Variables Containers) a umožňují nastavení konkrétní šablony pro daný po-
hled. Pomocí pohledového modelu lze tvořit hierarchickou strukturu, jeden ViewModel může
obsahovat i další potomky typu ViewModel, čímž je podpořena např. možnost vytvářet a sklá-
dat znovupoužitelné pohledy. Pro maximální zvýšení pohodlnosti je možné použít několik
způsobů, jak proměnnou pohledovému modelu, resp. šabloně „předat“, jak demonstruje
Výpis 13.
Výpis 13: Způsoby registrace šablonových proměnných (Zdroj: autor)
////////////////////////////////////////////////// // registrace proměnných v konstruktoru ViewModelu // metoda zpracování akce řadiče public function indexAction() { $viewModel = new \Zend\View\Model\ViewModel(array( ‘myVariable’ => ‘test’, ‘otherVariable’ => ‘test_2’,
)); return $viewModel;
} /////////////////////////////////////////////////// // registrace proměnných metodou public function indexAction() { $viewModel = new \Zend\View\Model\ViewModel(); // registrace proměnných každé zvlášť $viewModel->setVariable(‘myVariable’, ‘test’); $viewModel->setVariable(‘otherVariable’, ‘test_2’); // nebo lze použít hromadnou registraci // druhý parametr určuje, zda má dojít k přepsání existujícího // kontejneru s proměnnými či nikoliv $viewModel->setVariables(array( ‘myVariable’ => ‘test’, ‘otherVariable’ => ‘test_2’, ), true); return $viewModel; } ///////////////////////////////////////////////////
4 Porovnání PHP frameworků 46
// registrace pomocí magických metod public function indexAction() { $viewModel = new \Zend\View\Model\ViewModel(); $viewModel->myVariable = ‘test’; $viewModel->otherVariable = ‘test_2’; return $viewModel; }
V závislosti na použitém vykreslovači lze uvnitř šablon používat helpery. V případě
PHP vykreslovače lze seznam dostupných helperů ovlivnit pomocí třídy
Zend\View\HelperPluginManager39, která již obsahuje seznam všech výchozích helperů po-
skytovaných frameworkem. Přidat další helper lze buď pomocí patřičné metody správce hel-
perů (de facto se jedná o speciální podtyp třídy Zend\ServiceManager\ServiceManager, který
je, jak již bylo zmíněno, implementací service locatoru), či v rámci konfigurace modulu/apli-
kace.
Způsob použití helperů v šabloně nastiňuje Výpis 14, framework poskytuje relativně poho-
dlnou možnost zkráceného zápisu. Konkrétně se jedná o příklad použití escapování pro-
měnné. Upozornit je třeba na fakt, že escapování není tzv. kontextové, čili konkrétní způsob
escapování je zapotřebí manuálně určit použitím patřičné metody (liší se např. escapování
pro HTML, CSS, JS, URL apod.). Rovněž, samotný fakt, že escapování neprobíhá automa-
ticky, ale na základě požadavku vyvolaného použitím helperu, je celkový kód šablony po-
měrně nepřehledný a náchylný ke vzniku potenciálních bezpečnostních děr.
Výpis 14: Příklad použití helperu uvnitř šablony (Zdroj: autor)
// Příklad předpokládá: // 1] registraci helperu pod názvem escapeHtml, // 2] existence proměnné $myVariable. <div class=”test”> // vypíše escapovaný obsah proměnné $myVariable <?php echo $this->escapeHtml($myVariable); ?> </div>
Framework nabízí speciální sadu helperů souvisejících s problematikou lokalizace a inter-
nacionalizace. Nejobecnějším z nich je helper standardně registrovaný pod názvem
„translate“, který slouží k překladu zpráv. Nechybí helpery pro tvorbu lokalizovaných hod-
not týkajících se data a času, měn, ani číselných údajů.
39 Dále jako tzv. správce helperů.
4 Porovnání PHP frameworků 47
4.6.2 Nette
Základní komponenty pro tvorbu šablon představují třídy:
Nette\Templating\Template – obecný typ šablony; na vstupní zdroj šablony je možné
aplikovat tzv. filtry a následně ji vykreslit/uložit,
Nette\Templating\FileTemplate – speciální typ šablony, pro kterou platí, že je repre-
zentována fyzickým souborem na disku.
Obě implementace automaticky používají cache (konkrétně Nette\Caching\Cache), toto cho-
vání nelze nijak potlačit (lze ovlivnit pouze typ úložiště cache, viz kapitola 4.12.2 na straně
77).
Šablona jako taková není přímo spjata s určitým pohledem a lze ji např. použít i samostatně
bez dalších vrstev modelu MVC.
Rozhraní pro šablonu (Nette\Templating\ITemplate), resp. šablonu reprezentovanou soubo-
rem (Nette\Templating\IFileTemplate), nedeklaruje, že lze proměnné či helpery do šablony
registrovat. Registraci proměnných a helperů však třída Nette\Templating\Template defi-
nuje. Separace odpovědností (tak jak tomu je např. u Zend), je zde z pohledu komplexity
nízká, neboť z principu věci není ani zapotřebí40.
Nette však obsahuje svůj vlastní šablonovací jazyk Latte, který je právě oním nejčastějším
a výchozím filtrem, který je na danou šablonu aplikován a představuje jednu z klíčových
součástí frameworku. Na rozdíl od základu šablonového systému reprezentovaného zejména
třídou Nette\Templating\FileTemplate, je balíček Latte rozdělen do několika úrovní, resp.
tříd. Latte obsahuje speciální třídu pro parsování kódu šablony a jeho následnou kompilaci.
V rámci šablony lze používat tzv. makra, která jsou prakticky pouhým rozšířením možností
jazyka PHP. Každé makro je v rámci kompilace převedeno na odpovídající volitelný sled
PHP kódu, přičemž jazyk Latte umožňuje dvojí způsob jejich zápisu:
„klasický zápis“ pomocí složených závorek41,
„n:makro“ zápis, který lze použít uvnitř HTML tagu obdobně jako HTML atributy.
Rozdíl zápisu a zároveň elegantnost jazyka má za cíl představit Výpis 15.
Výpis 15: Příklad dvojího zápisu Latte maker (Zdroj: autor)
/////////////////////////// // klasický zápis
40 Rozčlenění je patrné až u konkrétního filtru Latte.
41 Ve skutečnosti se nemusí vždy nutně jednat o složené závorky, protože záleží na aktuálním
nastavení syntaxe – symbolu ohraničujícím zápis makra.
4 Porovnání PHP frameworků 48
<ul> {foreach $rows as $row} <li>{$row->name}</li> {/foreach} </ul> /////////////////////////// // n:makro zápis <ul> <li n:foreach=“$rows as $row“>{$row->name}</li> </ul>
Z příkladu Výpis 15 je patrné, že pro způsob jak proměnnou vypsat je přímočarý pomocí
uvedení jejího názvu do oddělovače maker (v tomto případě složené závorky). Příklad je
totožný s příkladem uvedeným u frameworku Zend za účelem vyzdvižení jedné podstatné
vlastnosti jazyka Latte, kterou je automatické escapování veškerého dynamicky generova-
ného výstupu. Escapování lze potlačit použitím helperu noescape42. Navíc, způsob
escapování je automaticky určen na základě kontextu, ve kterém má k výpisu dojít (HTML,
JS, apod.).
Kromě základních maker ovlivňujících běh skriptu známých z jazyka PHP (if, for, while,
atd.), Latte obsahuje i další pomocné, které usnadňují zápis některých specifických
konstrukcí nebo mají jiný speciální význam43:
makra související s výpisem formulářů, resp. formulářových prvků,
makra umožňující skládat několik šablon dohromady, definice rozvržení, dě-
dičnost šablon,
makro pro použití cache,
makra pro tvorbu aplikačních odkazů,
atd.
Vývojář rovněž není omezen výchozí sadou maker, jelikož Latte podporuje i registraci ma-
ker uživatelsky definovaných.
42 Z historických důvodu je možné escapování možné potlačit uvedením vykřičníku před
obsah, který má být vypsán. V současné verzi frameworku je však tento způsob již zavr-
žený a jeho použití vede k vyvolání chyby.
43 Kompletní seznam maker s jejich popisem a příklady užití lze nalézt např.
na http://doc.nette.org/cs/2.1/default-macros.
4 Porovnání PHP frameworků 49
Helpery jsou standardně zapisovány pomocí svislé čáry předcházející názvu helperu (např.
{$myVariable|trim}). Pro parametrizované helpery stačí za název helperu přidat dvojtečku
následovanou seznamem hodnot parametrů oddělenými čárkami (např.
{$myVariable|truncate:64}). Stejně jako makra je možné do šablony registrovat i helpery
vlastní.
4.6.3 Phalcon
Podobně jako u frameworku Nette je možné rozdělit šablonový systém Phalcon na dvě
vrstvy:
1. Vrstva pohled (třída Phalcon\Mvc\View) – vychází z modelu MVC,
2. Vlastní šablonovací jazyk Volt.
Pod pojmem šablona se vždy míní nějaký konkrétní pohled, obdobně jako je tomu u frame-
worku Zend, což představuje rozdíl mezi těmito frameworky a frameworkem Nette, který
chápe šablony jako prostředek pro tvorbu pohledu a navíc rozlišuje, zda je šablona reprezen-
tována fyzickým souborem, či nikoliv.
Rovněž API definované rozhraním, které implementuje (Phalcon\View\ViewInterface) je po-
měrně „košaté“ a kromě obecných metod pro registraci proměnných definuje i metody pro
nastavení cest ke zdrojovým souborům šablon, metody pro nastavení rozvržení a další44.
Metoda ViewInterface::registerEngines(array $engines) je jistým ekvivalentem metody
Template::registerFilter($callback), odhlédneme-li od rozdílu v názvosloví, jejich smysl
zůstává stejný – umožnit vývojáři registraci jiných šablonových vykreslovačů (tzv. adap-
térů). Součástí distribuce Phalcon jsou dva typy:
Phalcon\Mvc\View\Engine\Php – šablonovací jazyk PHP,
Phalcon\Mvc\View\Engine\Volt – rozšíření jazyka PHP (obdobně jako
Nette\Latte\Engine).
Pohled je navíc z povahy API vždy spojován s určitým řadičem a jeho akcí. Specifickým lze
nazvat i způsob, jakým lze ovlivnit (ne)vykreslení daného pohledu, kdy na rozdíl od frame-
worku Nette se tato možnost řídí nastavením přímo na tomto objektu. Jinými slovy, nemá-li
v rámci akce řadiče dojít k vykreslení pohledu, ale např. k přesměrování, je nutné vykreslení
manuálně deaktivovat viz Výpis 16.
Výpis 16: Způsob deaktivace vykreslení pohledu (Zdroj: (Phalcon Team and contributors, 2014))
class UsersController extends \Phalcon\Mvc\Controller
44 Viz dokumentace http://docs.phalconphp.com/en/latest/api/Phalcon_Mvc_ViewInter-
face.html.
4 Porovnání PHP frameworků 50
{ public function closeSessionAction() { // přesměrování $this->response->redirect('index/index'); // deaktivace vykreslení pohledu (šablony) $this->view->disable(); } }
Helpery jsou registrovány přímo do globálního DI kontejneru, bez nutnosti registrace
do konkrétních pohledů (rozdíl oproti ostatním frameworkům).
Šablonový vykreslovač Volt jako řada ostatních podporuje všechny základní konstrukce.
V porovnání s Latte se mírně liší svojí syntaxí, jak demonstruje Výpis 17. Ačkoliv jej lze
použít i samostatně, zůstává částečně závislý na DI kontejneru, který používá pro volání
dodatečných služeb použitých v šabloně45.
Výpis 17: Přehled základní syntaxe jazyka Volt (Zdroj: autor)
{# soubor s šablonou #} {# na rozdíl od Latte, nelze funkce jazyka PHP v makrech využívat napřímo (bez předchozí registrace), mimo makra příkazy PHP zapisovat lze #} {# kontrolní příkazy jsou ohraničeny složenou závorkou následovanou znakem procenta #} {# použití filtru (helperu) jehož název je uveden za svislou čárou pro spočítání počtu položek v kolekci #} {% if rows|count == 0 %} <p>No rows…</p> {% else %} <ul> {% for row in items %} {# vypsání hodnoty výrazu je ohraničeno dvojitými složenými závorkami #} <li>{{ row|e }}</li> {% endfor %} </ul> {% endif %}
45 http://docs.phalconphp.com/en/latest/reference/volt.html#inject-services-into-a-template
4 Porovnání PHP frameworků 51
Na rozdíl od Latte, kdy řídící i vypisovací příkazy jsou zapisovány pomocí stejného sym-
bolu, Phalcon tyto dva typy přísně rozlišuje a neumožňuje ani jejich případnou změnu. Na-
opak názvy proměnných mohou a musí být uváděny bez symbolu $. Helper e, resp. escape
slouží k escapování HTML výstupu. Pro escapování v odlišném kontextu je zapotřebí použít
tomu určené ekvivalenty (např. escape_css, escape_js). Omezení plynoucí z nutnosti expli-
citního používání escapovacích helperů lze částečně překonat za pomoci zvláštního makra,
kterým lze automatické escapování vynutit (byť pouze pro HTML).
Výpis 18: Automatické escapování v systému Volt (Zdroj: autor)
{# zápis: #} {{ foo|escape }} {# totožný s: #} {% autoescape true %} {{ foo }} {% endautoescape %}
Zdrojem kompilátoru (Phalcon\Mvc\View\Engine\Volt\Compiler) vstupního kódu šablony
může být kromě fyzického souboru i textový řetězec (proměnná typu string), pro jehož
kompilaci slouží metoda Compiler::compileString($viewCode, $extendsMode = NULL).
4.7 Formuláře
4.7.1 Zend
Formuláře v podání frameworku Zend zahrnují několik různých komponent. Za základní
komponentu lze označit Zend\Form\Element, resp. Zend\Form\Fieldset, jejímž speciálním ty-
pem je třída Zend\Form\Form. Třída Fieldset zastřešuje základní práci s formulářem, co se
týče definice jeho vnitřních prvků (elementů), přičemž platí, že může obsahovat i libovolný
počet dále vnořených Fieldsetů.
Způsobů, jak samotný formulář konstruovat, nabízí framework hned několik (liší se svojí
složitostí a možnostmi znovupoužitelnosti) (Zend Technologies Ltd., 2014):
1. Metoda postupného skládání formuláře ze samostatných elementů,
2. Použití výchozí tovární třídy Zend\Form\Factory,
3. Vytvoření formuláře děděním třídy Zend\Form\Form,
4 Porovnání PHP frameworků 52
4. Anotacemi definovaný formulář46.
Vývojář má k dispozici celou řadu jak klasických, tak i speciálních formulářových prvků
(elementů), které lze do formuláře přidávat (jmenný prostor Zend\Form\Element), pro tvorbu
uživatelsky definovaných elementů slouží rozhraní Zend\Form\ElementInterface.
Pro definici validačních pravidel slouží rozhraní vyčleněné mimo jmenný prostor formulářů
Zend\InputFilter\InputFilterProviderInterface, které definuje jedinou metodu
InputFilterProviderInterface::getInputFilterSpecification(), jejíž návratovou hodno-
tou je pole s definicí požadovaných pravidel. Validační pravidla jsou proto oddělena
od vlastních formulářových prvků, což může při tvorbě formulářů působit relativně zma-
tečně.
Validační pravidla jako taková jsou reprezentována třídami implementující rozhraní
Zend\Validator\ValidatorInterface. Ve stejném jmenném prostoru se pak nachází kromě
pravidel obvyklých (např. kontrola platnosti emailové adresy, délky řetězce, číselné hod-
noty) i několik dalších, které lze považovat za specifické (např. kontrola IBAN, číslo kreditní
karty, apod.). Autoři je navíc implementovali tak, aby případné validační chyby byly něko-
likastupňové, takže jedno validační pravidlo může obsahovat několik druhů typu chyb, které
tak mohou být uživateli výstižněji popsány pomocí zpráv, které přesněji popisují chybu,
ke které došlo. Každé další uživatelské pravidlo tedy musí být reprezentováno konkrétní
třídou.
Výpis 19: Příklad vytvoření definice formuláře pomocí tovární třídy (Zdroj: autor)
use Zend\Form\Factory, Zend\Validator; $factory = new Factory(); $form = $factory->createForm(array( 'elements' => array( array( 'spec' => array( 'type' => 'Zend\Form\Element\Text', 'name' => 'name', 'options' => array( 'label' => 'Name', ), ), ), ), 'input_filter' => array( 'name' => array(
46 Vyžaduje externí knihovnu Doctrine\Common, viz http://framework.zend.com/man-
ual/2.3/en/modules/zend.form.quick-start.html#using-annotations.
4 Porovnání PHP frameworků 53
// název je povinný (je nutné ho vyplnit) 'required' => TRUE, 'validators' => array( // délka názvu musí být alespoň 3 znaky new Validator\StringLength(array( 'min' => 3, )), ), ), ), ));
Zpracování hodnot formuláře spočívá v předání vstupních „syrových“ GET/POST dat in-
stanci formuláře pomocí metody Form::setData($data), následovaného voláním metody
pro validaci Form::isValid(). Pro získání zpracovaných dat slouží metoda Form::getData(),
pro získání chybových zpráv způsobených validací formuláře pak metoda
Form::getMessages().
Užitečnou funkcionalitu však přináší komponenty typu Zend\Stdlib\Hydrator\
HydratorInterface (Hydrátor), které lze s výhodou využít právě v souvislosti s formuláři.
Jejich smyslem je „poskytnout mechanismus pro naplnění objektu na základě vstupních dat
a obráceně” (Zend Technologies Ltd., 2014). Za pomocí Hydrátorů lze realizovat proces
v odborné sféře známý jako binding47. Binding v souvislosti s formuláři znamená
obousměrné namapování určité entity (třídy doménového modelu) na konkrétní formulář,
resp. jeho prvky. Příklad ilustruje Výpis 20 převzatý z oficiální dokumentace.
Výpis 20: Formulářový binding (Zdroj: (Zend Technologies Ltd., 2014))
$contact = new ArrayObject; $contact['subject'] = '[Contact Form] '; $contact['message'] = 'Type your message here'; $form = new Contact\ContactForm; $form->bind($contact); $data = array( 'name' => 'John Doe', 'email' => '[email protected]', 'subject' => '[Contact Form] \'sup?', ); $form->setData($data); if ($form->isValid()) { /*
47 Českým ekvivalentem může být např. svázání nebo napamování.
4 Porovnání PHP frameworků 54
obsah proměnné $contact: array( 'name' => 'John Doe', 'email' => '[email protected]', 'subject' => '[Contact Form] \'sup?', 'message' => 'Type your message here', ) */ }
Pro vykreslení formuláře uvnitř šablony lze použít několik předdefinovaných helperů. Těsně
před jeho vykreslením je však zapotřebí nejprve zavolat metodu Form::prepare(). Způsob
vykreslení se řídí stejným principem jako při tvorbě klasického HTML formuláře (uvedený
sled předpokládá použití v rámci šablony s existující proměnnou $form reprezentující in-
stanci předem definovaného formuláře):
1) Vykreslení otevírací značky (tagu) $this->form()->openTag($form);,
2) Vykresleni jednotlivých formulářových prvků (elementů):
V závislosti na typu formulářového prvku lze vykreslit jeho popisek (angl.
label), samotný prvek (angl. input), chybové zprávy pro daný prvek,
Pro výchozí formulářové prvky existují odpovídající helpery (třídy ze jmen-
ného prostoru Zend\Form\View\Helper s názvem Form<TypElementu>), pří-
padně lze použít obecnou variantu (třída FormInput),
Pro vykreslení všech částí najednou pomocí jediného příkazu lze použít hel-
per $this->formRow(ElementInterface $element = NULL).
3) Vykreslení ukončovací značky (tagu) $this->form()->closeTag();.
4.7.2 Nette
Podobně jako framework Zend, Nette formulář chápe jako komponentu skládající se z lo-
gických celků, tzv. kontejnerů48 (třída Nette\Forms\Container, která je speciálním typem
kontejneru ve smyslu komponentového modelu Nette). Proto lze formulář skládat z libovol-
ných dalších „pod-formulářů“, přesněji řečeno kontejnerů, obdobně jako to umožňuje Zend.
Formulář jako celek je reprezentován třídou Nette\Forms\Form a je speciálním typem kontej-
neru. Tvorbu jeho definice framework podporuje výhradně objektově orientovaným způso-
bem pomocí metod Form::add<TypPrvku>(…), ve většině případů je povinně vyžadován pouze
48 Dále se pod pojmem kontejner má na mysli formulářový kontejner.
4 Porovnání PHP frameworků 55
název takto přidané komponenty (povinnost deklarace jedinečného názvu vyplývá z kompo-
nentového modelu).
Validační pravidla jsou definována na rozdíl od frameworku Zend pro každý prvek zvlášť
a umožňují navíc vytvářet podmínky, za kterých je validace jednotlivých prvků prováděna.
Pravidla jsou zaregistrována pomocí volitelné kombinace metod49:
1. BaseControl::addRule($operation, $message = NULL, $arg = NULL) – přidání vali-
dačního pravidla s volitelnou zprávou, která je určena k zobrazení uživateli v případě
nesplnění podmínek daných pravidlem; některá pravidla vyžadují uvedení hodnoty
pro 3. parametr, který je jinak volitelný (např. max./min. délka řetězce); jako hod-
notu parametru $operation lze uvést i callback, resp. anonymní funkci, která před-
stavuje např. uživatelsky definované pravidlo (její výstupní hodnota by měla být
typu boolean),
2. BaseControl::addCondition($operation, $value = NULL) – stanovení podmínky
pro uplatnění následujících validačních pravidel,
3. BaseControl::addConditionOn(IControl $control, $operation, $value = NULL) –
stejné jako v předchozím bodě s tím rozdílem, že podmínku je možné aplikovat na
jiný prvek.
Kromě obecně platných pravidel (např. validace emailu, číselné hodnoty, regulární výrazy,
povinnost vyplnění hodnoty, min./max. délka apod.), existuje možnost přidání vlastních
pravidel pomocí callbacků či anonymních funkcí. Pro kontrolu, že formulář neobsahuje
chyby a zároveň byl korektně odeslán, slouží metoda Form::isSuccess(). Zpracované hod-
noty vrací metoda Container::getValues(), resp. Form::getValues($asArray = FALSE).
Vstupní data si formulář dokáže získat sám, proto je formuláři není nutné předávat manuálně.
Výpis 21: Příklad definice formuláře (Zdroj: autor)
use Nette\Forms\Form; // vytvoření přihlašovacího formuláře $form = new Form(); $form->addText(‘login’, ‘Login’) ->setRequired(‘Prosím zadejte Váš login.’) ->addRule(Form::EMAIL, ‘Prosím, zkontrolujte platnost e-mailu.’) ->addRule(function (Nette\Forms\IControl $control) { // zde může být implementována např. logika ověření, // zda zadaný e-mail je aktivován, apod. if (...) {
49 Jedná se o metody třídy Nette\Forms\Controls\BaseControl, jejímž potomkem jsou
všechny konkrétní typy formulářových prvků.
4 Porovnání PHP frameworků 56
return FALSE; } return TRUE; }, ‘Váš účet byl zablokován.’); $form->addPassword(‘pass’, ‘Heslo’) ->setRequired(‘Prosím, zadejte Vaše heslo.’); $form->addSubmit(‘Prihlásit’);
Vykreslení celého formuláře obstarává tzv. vykreslovač (třída implementující rozhraní
Nette\Forms\IFormRenderer) a díky přepsání metody Form::__toString(), jej lze snadno vy-
kreslit např. za pomoci výchozího vykreslovače
Nette\Forms\Rendering\DefaultFormRenderer, který obsahuje množství parametrů, kterými
lze vykreslení ovlivnit. Pro manuální vykreslení lze s výhodou využít systému Latte, který
obsahuje specializovaná makra, viz Výpis 22.
Výpis 22: Příklad použití Latte maker pro manuální vykreslení formuláře (Zdroj: autor)
{# soubor s šablonou #} {# předpokládá existenci komponenty myForm, viz dále #} {form myForm class => ‘myForm’} {# makra podporují nastavení HTML atributů #} {label login /}{input login} {# input typu text #} {label pass /}{input pass} {# input typu password #} {input submitForm} {# odesílací tlačítko typu submit #} {/form}
Formuláře jsou z pohledu komponentového modelu Nette specifickou komponentou, jelikož
na rozdíl od komponent ostatních je nativně podporována jejich lokalizovatelnost. Zároveň
pro použití formuláře v rámci Presenteru slouží tomuto přizpůsobená třída
Nette\Application\UI\Form, která již funguje na principu tzv. signálů.
Další ojedinělou a bezpochyby užitečnou vlastností Nette je (alespoň co se týče porovnáva-
ných frameworků), že součástí distribuce je i javascriptový obslužný soubor
client_side\netteForms.js pro provádění validace na straně klienta, který podporuje všechny
základní validační pravidla a umožňuje registraci obslužného javascriptu i pro uživatelsky
definovaná pravidla.
4.7.3 Phalcon
Třidou reprezentující formulář je typ Phalcon\Forms\Form, který se na rozdíl od ostatních
frameworků může skládat pouze z tzv. elementů (třídy implementující rozhraní
Phalcon\Forms\ElementInterface). Pro Phalcon je tedy typickým znakem, že ve výchozím
stavu neumožňuje formulář rozdělit na samostatné logické části ani pomocí tzv. fieldsetů.
4 Porovnání PHP frameworků 57
Způsob tvorby formuláře je principiálně podobný tomu, který byl představen v sekci Nette
i Zend. Jednotlivé prvky jsou přidávány obecnou metodou Form::add($element, $postion =
null, $type = null). Z porovnávaných frameworků obsahuje distribuce nejmenší počet typů
elementů, které lze ihned použít.
K elementům lze přidávat validační pravidla pomocí metody
ElementInterface::addValidator($validator). Pravidla jsou reprezentována tzv. validátory
(třídy implementující rozhraní Phalcon\Validation\ValidatorInterface), sadu výchozích
dostupných validátorů obsahuje jmenný prostor Phalcon\Validation\Validator. Tvorba
vlastních pravidel zákonitě vede k nutnosti deklarace dodatečných tříd.
Pro validaci formuláře slouží metoda Form::isValid($data = NULL, $entity = NULL), která
přijímá jako parametr zejména vstupní data formuláře odeslané uživatelem (v nejjedno-
dušším případě superglobální pole $_GET/$_POST).
Formuláře poskytují podobný mechanismus pro binding objektů jako framework Zend.
Vstupní objekt lze k formuláři připojit buď při jeho vytvoření (parametr konstruktoru) nebo
dodatečně pomocí metody Form::setEntity($entity). Názvy proměnných, které musejí být
pochopitelně deklarované jako veřejné, musí korespondovat s názvy příslušných formulářo-
vých prvků, podporovány jsou však i tzv. gettery a settery, které mají před třídními proměn-
nými přednost. Má-li však dojít ke zpětnému naplnění entity daty z formuláře, je zapotřebí
zavolat metodu Form::bind($data, $entity, $whitelist = NULL), případně tento krok vy-
nechat a data spolu s instancí vstupní entity předat metodě Form::isValid($data = NULL,
$entity = NULL). Tento krok je bohužel pro zaručení správného chování nutný a lze jej
považovat za poněkud zvláštní, protože neprobíhá automaticky.
Výpis 23: Příklad definice formuláře a jeho zpracování (Zdroj: autor)
// předpokládá se existence třídy SomeEntity s definovanými metodami // SomeEntity::setName($name) a SomeEntity::getName(). use Phalcon\Forms\Form, Phalcon\Forms\Element, Phalcon\Validation\Validator; $entity = new SomeEntity(); $entity->setName('default_name'); // $entity->getName() => ‘default_name’ $form = new Form($entity); $form->add(new Element\Text('name')); $form->get(‘name’)->addValidator(new Validator\PresenceOf()); $form->add(new Element\Submit('submit')); // $form->getValue(‘name’) => ‘default_name’ if ($form->isValid($_POST, $entity)) {
4 Porovnání PHP frameworků 58
// uložení entity... // $entity->getName() => hodnota zadaná ve formuláři }
Vykreslit formulář lze dvěma způsoby:
1. Pomocí PHP kódu,
2. Pomocí šablonového systému Volt.
První metoda spočívá v kombinaci ručně psaného HTML (např. otevírací a ukončovací
značky tagu form) a používání kombinace metod Form::render($name, $attributes = NULL)
pro vykreslení formulářového prvku, resp. Form::label($name, $attributes = NULL)
pro vykreslení jeho popisku.
Alternativní metodou je využít šablonového systému Volt a sady předregistrovaných
funkcí50, které pro generování HTML kódu vnitřně používají tzv. užitkovou třídu (angl.
utility class) Phalcon\Tag. Obzvláště u této metody může vyvstat problém s udržitelností
zdrojového kódu formuláře, protože kód HTML formuláře nemusí odpovídat jeho logické
definici např. uvnitř řadiče. Každou změnu ve struktuře a názvosloví je pro zachování funkč-
nosti nutné promítnout i do kódu v šabloně.
4.8 Session a Cookies
4.8.1 Zend
Zend poskytuje vývojáři plnohodnotnou abstrakci od používání nativních funkcí PHP sou-
visejících se session. Balík komponent ze jmenného prostoru Zend\Session zajišťuje
následující funkce:
1. Konfigurace session – rozhraní Zend\Session\Config\ConfigInterface – nastavení
základních vlastností session jako je název nebo doba životnosti,
2. Session kontejner – třída Zend\Session\Container – slouží jako jednotné místo
pro uchovávání session dat, která tak lze ukládat do logicky oddělených částí (po-
mocí jmenného prostoru) (Zend Technologies Ltd., 2014),
3. Session manažer – rozhraní Zend\Session\ManagerInterface - správa session jako
celku (např. inicializace a ukončení session),
50 http://docs.phalconphp.com/en/latest/reference/volt.html#using-tag-helpers
4 Porovnání PHP frameworků 59
4. Pro ukládání a čtení session dat slouží rozhraní
Zend\Session\SaveHandler\SaveHandlerInterface,
5. Úložiště session – rozhraní Zend\Session\Storage\StorageInterface – určuje typ
umístění session dat,
6. Validátory – rozhraní Zend\Session\Validator\ValidatorInterface – slouží ke sní-
žení rizika podvržení session (angl. session hijacking) (Zend Technologies Ltd.,
2014).
Jako význačná vlastnost se jeví skutečnost, že téměř všechny komponenty jsou vázány obec-
nými rozhraními, čili není problém nahradit výchozí komponenty za jiné. Za zmínku stojí
také fakt, že ne všechny komponenty vnitřně pracují přímo s nativními prostředky PHP
pro práci se session51, aby tak bylo dosaženo lepších možností nasazení např. na jiné sys-
témy.
Cookie, jelikož je druhem HTTP hlavičky, je reprezentována třídou
Zend\Http\Header\SetCookie. Pro přístup k seznamu cookies přijatých v HTTP požadavku
lze použít metody Zend\Http\Request::getCookie(). Přiklad použití cookies je uveden v ná-
sledujícím výpisu.
Výpis 24: Příklad použití cookies (Zdroj: autor)
// TestController.php use Zend\Http\Header\SetCookie; class TestController extends Zend\Mvc\Controller\AbstractActionController { public function indexAction() { // příchozí cookies $requestCookies = $requestHeaders = $this->getRequest()->getCookie(); // vytvoření nové HTTP cookie hlavičky $myCookie = new SetCookie( ‘myCookie’, // název ‘testValue’, // hodnota time() + 7200, // životnost ‘/’ // cesta ); // výstupní hlavičky HTTP odpovědi $responseHeaders = $this->getResponse()->getHeaders(); // přidání vytvořené cookie hlavičky
51 Např. funkce session_start() a superglobální proměnná $_SESSION.
4 Porovnání PHP frameworků 60
$responseHeaders->addHeader($myCookie); // cookies odesílané spolu v HTTP odpovědi // již obsahuje $myCookie $responseCookies = $this->getResponse()->getCookie(); } }
4.8.2 Nette
Složitost abstrakce session je v porovnání se Zend výrazně nižší. Session data jsou rovněž
rozdělena do samostatných jmenných prostorů. V zásadě se lze setkat pouze s těmito kom-
ponentami:
1. Třída Nette\Http\Session – obálka nad nativními PHP funkcemi pro inicializaci
a ukončení session, pomocí které lze session zároveň konfigurovat; standardně je
součástí výchozích služeb frameworku a není ji nutné v rámci DI kontejneru manu-
álně vytvářet,
2. Session sekce - třída Nette\Http\SessionSection – kontejner pro session data (ob-
doba Zend\Session\Container),
3. Úložiště session dat - rozhraní Nette\Http\ISessionStorage (obdoba
Zend\Session\Storage\StorageInterface) – distribuce neobsahuje žádné jeho vý-
chozí implementace; od verze PHP 5.4 je navíc označen jako zavržený, jelikož PHP
definuje nativní rozhraní SessionHandlerInterface.
Výpis 25: Ukázka použití SessionSection v presenteru (Zdroj: autor)
class TestPresenter extends Nette\Application\UI\Presenter { /** @var string */ const MY_SESSION_SECTION_NAME = 'my_session_section_name'; public function actionDefault() { $sessionSection = $this->getSession(static::MY_SESSION_SECTION_NAME); $sessionSection->foo = 'bar'; echo $sessionSection->foo; // vypíše: // bar } }
4 Porovnání PHP frameworků 61
Pro zpracování příchozích cookies slouží metoda rozhraní
Nette\Http\IRequest::getCookie($key, $default = NULL). Pro odeslání cookies formou
HTTP odpovědi pak metoda rozhraní Nette\Http\IResponse::setCookie($name, $value,
$expire, $path = NULL, $domain = NULL, $secure = NULL, $httpOnly = NULL). Pro repre-
zentaci cookie tedy neexistuje žádná frameworkem definovaná třída. V porovnání s frame-
workem Zend však Nette umožňuje jejich mazání skrze metodu
IResponse::deleteCookie($name, $path = NULL, $domain = NULL, $secure = NULL), vývojář
je proto odstíněn od způsobu, jakým ke smazání ve skutečnosti dojde (vynulování životnosti
dané cookie).
4.8.3 Phalcon
Session komponenty Phalcon jsou podobně jako u Nette oproti frameworku Zend relativně
málo rozčleněny. Pro práci se session ve frameworku Phalcon jsou zásadní následující roz-
hraní (jmenný prostor Phalcon\Session):
1. AdapterInterface,
2. BagInterface.
Upozornit je třeba na fakt, že dojde-li v rámci běhu skriptu k několikanásobnému instancio-
vání třídy Phalcon\Session\Adapter\Files (základní implementace AdapterInterface),
resp. nastartování session v jedné z nich, metoda Files::isStarted() v ostatních instancích
vrací FALSE, i když již session nastartována byla (byť v rámci jiné instance téže třídy).
Výpis 26: Příklad použití třídy Bag (Zdroj: autor)
$bag = new Bag(‘myBagNamespace’); $bag->foo = ‘bar’; // var_dump($bag->foo); // vypíše: // string(3) "bar"
Výpis 27: Příklad použití třídy Files (Zdroj: autor)
$files = new Files(array( 'uniqueId' => 'myUniqueNamespaceName', )); if (!$files->isStarted()) { // zde může potenciálně dojít k vyvolání // systémové chyby typu E_NOTICE $files->start(); }
4 Porovnání PHP frameworků 62
$files->foo = 'bar'; // var_dump($files->foo); // vypíše: // string(3) "bar"
Třída Phalcon\Http\Response\Cookies nabízí zjednodušený způsob práce s cookies, protože
je není potřeba získávat z HTTP požadavku, existující cookies jsou automaticky součástí
HTTP odpovědi. Ke službě lze přistoupit v rámci DI kontejneru, podmínkou použití je buď
nastavení tzv. kryptovacího klíče (v případě, že není nastaven, dojde k upozornění hláškou)
nebo vypnutí kryptování. (Phalcon Team and contributors, 2014)
Výpis 28: Způsob zprovoznění služby cookies v rámci DI kontejneru (Zdroj: (Phalcon Team and
contributors, 2014))
////////////////////////////////// // 1. způsob // deaktivace kryptování $di->set('cookies', function() { $cookies = new Phalcon\Http\Response\Cookies(); $cookies->useEncryption(FALSE); return $cookies; }); ////////////////////////////////// // 2. způsob // nastavení kryptovacího klíče $di->set('crypt', function() { $crypt = new Phalcon\Crypt(); $crypt->setKey('#1dj8$=dp?.ak//j1V$'); return $crypt; });
Stejně jako ve frameworku Nette, nejsou jednotlivé cookies reprezentovány nějakou speci-
fickou třídou, nýbrž pro jejich nastavení, resp. získání slouží metoda
Phalcon\Http\Response\CookiesInterface::set($name, $value = NULL, $expire = NULL,
$path = NULL, $secure = NULL, $domain = NULL, $httpOnly = NULL),
resp. Phalcon\Http\Response\CookiesInterface::get($name).
4 Porovnání PHP frameworků 63
4.9 Databázová abstrakce
4.9.1 Zend
Adaptér (třída Zend\Db\Adapter\Adapter) je základní komponentou zastřešující práci
s tzv. ovladači (angl. drivers) – třídami implementující rozhraní
Zend\Db\Driver\DriverInterface – určenými reprezentující jednotlivé databázové systémy.
Abecedně seřazeno se jedná o následující třídy (jmenný prostor Zend\Db\Driver):
IbmDb2\IbmDb2,
Mysqli\Mysqli,
Oci8\Oci8,
Pdo\Pdo,
Pgsql\Pqsql,
Sqlsrv\Sqlsrv.
Příklad použití Mysqli adaptéru pro získání seznamu všech knih uložených v databázi zná-
zorňuje následující výpis.
Výpis 29: Příklad použití databázového adaptéru (Zdroj: autor)
use Zend\Db\Adapter\Adapter, Zend\Db\Adapter\Driver\Mysqli; $connectionInfo = array( 'hostname' => '127.0.0.1', // localhost 'username' => 'foo', 'password' => 'bar', 'database' => 'test', ); $connection = new Mysqli\Connection($connectionInfo); $driver = new Mysqli\Mysqli($connection); $adapter = new Adapter($driver); $statement = $adapter->query('SELECT * FROM book'); $results = $statement->execute(); // vypíše názvy všech nalezených knih foreach ($results as $row) { echo ($row['name']) . '<br>'; }
4 Porovnání PHP frameworků 64
Předchozí příklad lze přepsat do upravené podoby, ve které je dotaz konstruován přes spe-
ciální objektově orientované API:
Výpis 30: Tvorba dotazu za pomocí objektově orientovaného API (Zdroj: autor)
use Zend\Db\Adapter\Adapter, Zend\Db\Adapter\Driver\Mysqli, Zend\Db\Sql\Sql; $connectionInfo = array( 'hostname' => '127.0.0.1', // localhost 'username' => '', 'password' => '', 'database' => 'test', ); $connection = new Mysqli\Connection($connectionInfo); $driver = new Mysqli\Mysqli($connection); $adapter = new Adapter($driver); $sql = new Sql($adapter); $select = $sql->select(); $select->from('book'); $statement = $adapter->query($sql->getSqlStringForSqlObject($select)); $results = $statement->execute(); // vypíše názvy všech nalezených knih foreach ($results as $row) { echo $row['name'] . '<br>'; }
Pro konstrukci DDL dotazů lze využít vyčleněného API poskytovaného třídou
Zend\Db\Sql\Ddl, příklad použití je uveden v následujícím výpisu. Jeho možnosti jsou sice
omezené, nicméně základní operace, jako jsou vytváření a mazání tabulek podporovány jsou
(každá operace reprezentována zvláštní třídou)
Výpis 31: Příklad sestavení DDL dotazu objektově orientovaným způsobem (Zdroj: autor)
use Zend\Db\Adapter\Adapter, Zend\Db\Adapter\Driver\Mysqli, Zend\Db\Sql\Sql, Zend\Db\Sql\Ddl; $connectionInfo = array( 'hostname' => '127.0.0.1', // localhost 'username' => '', 'password' => '', 'database' => 'test', );
4 Porovnání PHP frameworků 65
$connection = new Mysqli\Connection($connectionInfo); $driver = new Mysqli\Mysqli($connection); $adapter = new Adapter($driver); // definice nové dočasné tabulky (druhý parametr) $ddl = new Ddl\CreateTable('my_temporary_table', TRUE); $ddl->addColumn(new Ddl\Column\Integer('id', FALSE)); $ddl->addColumn(new Ddl\Column\Varchar('name', 255)); $sql = new Sql($adapter); $adapter->query( $sql->getSqlStringForSqlObject($ddl), // vygenerování výsledného SQL Adapter::QUERY_MODE_EXECUTE // příkaz se vykoná okamžitě );
Obdobně jako v případě formulářů je i zde možné použít tzv. hydrátorů, pomocí kterých lze
výsledky (řádky tabulky) převést na instance uživatelsky definovaných tříd reprezentujících
obvykle tzv. business entity doménového modelu. K tomuto účelu slouží třída
Zend\Db\ResultSet\HydratingResultSet, které stačí předat konkrétní typ hydrátoru a instanci
výstupní třídy. Použitím metody HydratingResultSet::initialize($dataSource) následně
dojde k procesu mapování vstupních hodnot řádků na volitelné třídní proměnné nově vytvo-
řených instancí objektu reprezentující zvolenou entitu.
Pro účely získání užitečných informací o prováděných dotazech lze použít tzv. profiler (třída
Zend\Db\Adapter\Profiler\Profiler), který poskytuje data o době vykonání dotazu a jeho
skutečné podobě ve formě SQL. Samotné ukládání (logování) těchto dat zůstává již na vý-
vojáři.
4.9.2 Nette
Nette stejně jako Zend podporuje několik nejpoužívanějších databázových systémů. Termi-
nologie zavedené v této souvislosti se rovněž neliší – zavedení tzv. ovladačů (tříd implemen-
tujících rozhraní Nette\Database\ISupplementalDriver). Podporované ovladače se nacházejí
ve jmenném prostoru Nette\Database\Drivers:
MsSqlDriver,
MySqlDriver,
OciDriver,
OdbcDriver,
PgSqlDriver,
4 Porovnání PHP frameworků 66
Sqlite2Driver,
SqliteDriver,
SqlsrvDriver.
V principu existují v Nette (stejně jako ve frameworku Zend) dva způsoby pokládání dotazů:
1. Použití metody Nette\Database\Context::query($statement) pro tvorbu dotazů po-
mocí textového řetězce ve formátu SQL,
2. Použití tzv. tabulkového výběru Nette\Database\Table\Selection, pomocí kterého
lze tvořit dotazy již ve stylu objektově orientovaného API.
Příklad uvedený níže znázorňuje princip použití druhého způsobu.
Výpis 32: Příklad použití tabulkového výběru v Nette (Zdroj: autor)
use Nette\Database\Connection, Nette\Database\Context; $connection = new Connection('mysql:host=127.0.0.1;dbname=test'); $context = new Context($connection); $selection = $context->table('book'); // vypíše názvy všech knih foreach ($selection->fetchAll() as $book) { echo $book->name . PHP_EOL; } // vypíše názvy všech knih, jejichž autorem je Dan Brown foreach ($selection->where(array('author' => 'Dan Brown')) as $book) { echo $book->name . PHP_EOL; } // vypíše seznam všech knih a názvy k nim přiřazených tagů foreach ($selection as $book) { echo $book->name . ':' . PHP_EOL; foreach ($book->related('book_tag') as $bookTag) { echo $bookTag->tag->name . PHP_EOL; } echo PHP_EOL; }
4 Porovnání PHP frameworků 67
Poslední z příkladů má za cíl demonstrovat možnost jednoduchého dotazování se do refe-
renčních tabulek propojených skrze cizí klíče bez nutnosti psát samostatné omezující52 do-
tazy. Navíc, díky „chytré“ implementaci se ve skutečnosti provedou pouze tři dotazy.
Následně se při každém průchodu cyklu již jen odfiltrují patřičné řádky dle referenční vazby.
Nette jako jediný z porovnávaných frameworků neposkytuje žádné vyhrazené API pro sklá-
dání DDL dotazů.
Logování dotazů, ač je ponecháno na vývojáři, je možné jej realizovat poměrně snadno díky
události Connection::onQuery, která vyvstane po (ne)úspěšném vykonání SQL dotazu.
Výpis 33: Princip zpracování události Connection::onQuery (Zdroj: autor)
use Nette\Database\Connection, Nette\Database\Context, Nette\Database\ResultSet; $connection = new Connection('mysql:host=127.0.0.1;dbname=test'); $context = new Context($connection); $connection->onQuery[] = function (Connection $connection, $result) { // v případě, že dojde během pokládání dotazu k vyvolání výjimky, // je její hodnota předána v hodnotě parametru $result, // jinak parametr obsahuje výsledek dotazu if ($result instanceof ResultSet) { echo $result->getQueryString() . PHP_EOL; } else { error_log($result->message); } }; $selection = $context->table('book');
4.9.3 Phalcon
Seznam standardně podporovaných databázových systémů čítá čtyři třídy – adaptéry
(jmenný prostor Phalcon\Db\Adapter\Pdo):
Mysql,
Oracle,
Postgresql,
52 Myšleno dotazy restriktivního charakteru.
4 Porovnání PHP frameworků 68
Sqlite.
Phalcon se odlišuje od ostatních frameworků tím, že API pro objektově orientované skládání
souvisí s konkrétními modely, což jsou obecně třídy implementující rozhraní
Phalcon\Mvc\ModelInterface (výchozím předkem pro nejrychlejší tvorbu uživatelských mo-
delů je třída Phalcon\Mvc\Model). Model jako takový v podstatě reprezentuje databázovou
tabulku jako takovou, zároveň však i jeden záznam této tabulky.
Pro manipulaci s modely slouží vlastní „vysoko-úrovňový“ jazyk PHQL (Phalcon Query
Language). V praxi to znamená, že v dotazech je a musí být abstrahováno od názvů fyzic-
kých tabulek, resp. sloupců a místo nich se použije názvů modelů (tříd), resp. třídních pro-
měnných. Pro konstrukci dotazů objektově orientovaným způsobem lze využít třídy
Phalcon\Mvc\Model\Query\Builder, viz následující výpis.
Výpis 34: Příklad použití třídy Builder pro konstrukci PHQL dotazu
(Zdroj: (Phalcon Team and contributors, 2014))
// předpokládá existence modelů Robots a RobotsParts // $builder instanceof Phalcon\Mvc\Model\Query\BuilderInterface $rows = $builder->from('Robots') ->join('RobotsParts') ->orderBy('Robots.name') ->getQuery() ->execute();
Aplikační rozhraní adaptéru (vyplívající z rozhraní Phalcon\Db\AdapterInterface) je po-
měrně „košaté“, jelikož kromě metod určených k získávání informací o struktuře databázo-
vých objektů, obsahuje i metody pro konstrukci DDL dotazů, jejichž výsledná podoba je
pochopitelně vnitřně korigována tak, aby odpovídala specifikům konkrétního databázového
systému. I ty však, stejně jako v případě Zend, mají svá omezení (nelze např. určit kolaci
tabulky/sloupce).
Výpis 35: Ukázka přístupu k MySQL databázi v prostředí Phalcon (Zdroj: autor)
use Phalcon\Db\Adapter\Pdo\Mysql, Phalcon\Db\Column; $config = array( 'host' => '127.0.0.1', // localhost 'dbname' => 'test', ); $mysql = new Mysql($config); // dotaz vytvořený „manuálně“ $books = $mysql->query('SELECT * FROM `book`')->fetchAll(); // vypíše názvy všech nalezených knih
4 Porovnání PHP frameworků 69
foreach ($books as $book) { echo $book['name'] . PHP_EOL; } // vloží do tabulky `book` nový záznam (novou knihu) $mysql->insert( // název tabulky 'book', // hodnoty array( 6, 'My book', 'John Doe', date('Y-m-d'), ), // názvy sloupců array( 'id', 'name', 'author', 'date_published', ) ); // pokusí se vytvořit novou tabulku `test_table` v databázi `test` $mysql->createTable( 'test_table', 'test', array( 'columns' => array( new Column( 'id', array( 'type' => Column::TYPE_INTEGER, 'notNull' => TRUE, 'unsigned' => TRUE, 'primary' => TRUE, 'autoIncrement' => TRUE, ) ), new Column( 'name', array( 'type' => Column::TYPE_VARCHAR, 'size' => 255, 'notNull' => TRUE, ) )
4 Porovnání PHP frameworků 70
), ) );
Podobně jako ve frameworku Zend lze (nejen) pro účely logování využít událostí53, které
jsou za předpokladu připojeného správce událostí (EventsManager) automaticky vyvolávány,
z nichž nejdůležitější je asi ta následující po vykonání SQL dotazu.
Výpis 36: Způsob zpracování databázových událostí v prostředí Phalcon (Zdroj: autor)
use Phalcon\Db\Adapter\Pdo\Mysql, Phalcon\Db\Profiler, Phalcon\Events\Manager; $profiler = new Profiler(); $eventsManager = new Manager(); $eventsManager->attach( 'db:beforeQuery', function ($event, $mysql) use ($profiler) { $profiler->startProfile($mysql->getSQLStatement()); var_dump('before query: ' . $mysql->getSQLStatement()); } ); $eventsManager->attach( 'db:afterQuery', function ($event, $mysql) use ($profiler) { $profiler->stopProfile(); var_dump('after query: ' . $mysql->getSQLStatement()); } ); $mysql = new Mysql(array( 'host' => '127.0.0.1', // localhost 'dbname' => 'test', )); $mysql->setEventsManager($eventsManager); $books = $mysql->query('SELECT * FROM `book`'); var_dump($profiler->getLastProfile()->getTotalElapsedSeconds()); // vypíše: // string(34) "before query: SELECT * FROM `book`"
53 Seznam a popis všech událostí je k dispozici na http://docs.phalconphp.com/en/latest/re-
ference/db.html#database-events.
4 Porovnání PHP frameworků 71
// string(33) "after query: SELECT * FROM `book`" // float(0.00037813186645508)
4.10 Autorizace, autentizace
4.10.1 Zend
Pro autentizaci uživatele framework definuje tzv. adaptéry. Za adaptér lze považovat jakou-
koliv třídu, která implementuje rozhraní Zend\Authentication\Adapter\AdapterInterface
deklarující jedinou metodu AdapterInterface::authenticate(). Účelem této metody je vrátit
výsledek ve formě Zend\Authentication\Result (v případě, že autentizaci nelze z nějakého
důvodu provést, měla by metoda vyvolat výjimku typu
Zend\Authentication\Adapter\Exception\ExceptionInterface). Několik výchozích typů
adapterů obsahuje již zmíněný jmenný prostor Zend\Authentication\Adapter.
Na základě výsledku autentizace lze pak určit, zdali byla úspěšná. Metodu
Result::getCode() je možné využít např. pro rozlišení různých chybových stavů, na základě
kterých autentizace selhala. Třídě by mělo být při chybné autentizaci předáno pole souvise-
jících chybových zpráv, které pak lze následně získat pomocí metody
Result::getMessages(). V případě úspěšné autentizace by měla metoda
Result::getIdentity() vracet tzv. identitu (např. objekt reprezentující uživatele), její přes-
nou podobu však třída nespecifikuje a je tedy plně v kompetenci vývojáře, jaký konkrétní
datový typ bude metoda vracet.
Nadstavbou adaptérů, která umožňuje i ukládání výsledku úspěšné autentizace (identity) je
třída Zend\Authentication\AuthenticationService (autentizační třída), která implementuje
rozhraní autentizační služby Zend\Authentication\AuthenticationServiceInterface. Au-
tentizační třída pro ukládání identity používá zvláštní rozhraní reprezentující typ úložiště
Zend\Authentication\Storage\StorageInterface (ve výchozím stavu je použit typ
Zend\Authentication\Storage\Session).
Navzdory tomu, že framework rozlišuje dva specifické typy autorizačního mechanismu,
žádné obecné rozhraní pro definici autorizátoru nedeklaruje. Jmenný prostor
Zend\Permissions obsahuje následující dvě sady tříd a rozhraní:
1) ACL,
2) Rbac.
Metody řízení přístupů jsou si navzájem podobné, obě vycházejí z principu existence urči-
tých rolí, kterým je umožněn, či zakázán přístup k určitému zdroji. Rozdíl lze vypozorovat
4 Porovnání PHP frameworků 72
ze signatury metod AclInterface::isAllowed($role = null, $resource = null, $privilege
= null) a Rbac::isGranted($role, $permission, $assert = null). ACL akcentuje potřebu
řízení přístupu na základě rolí, kterým je povolen/zakázán přístup k určitým zdrojům
(pro přesnější specifikaci typu oprávnění slouží třetí nepovinný parametr – např. čtení, zápis
apod.), zatímco Rbac klade větší důraz na definování vztahu rolí a k nim definovaných opráv-
nění.
Zend jde co do možností zvýšení zabezpečení tak daleko, že pro hešování hesel deklaruje
vlastní rozhraní Zend\Crypt\Password\PasswordInterface, z nich vychází dvě základní im-
plementace (jmenný prostor Zend\Crypt\Password) (Zend Technologies Ltd., 2014):
Bcrypt – implementuje doporučovaný způsob hešování hesel tzv. bcrypt algoritmus,
Apache – podporuje hešovací mechanismy dané webovým serverem Apache54.
4.10.2 Nette
Pro ověření identity uživatele slouží tzv. autentizátor – třída implementující rozhraní
Nette\Security\IAuthenticator, resp. jeho metoda IAuthenticator::authenticate(array
$credentials), která na rozdíl od frameworku Zend přijímá jako parametr identifikační
údaje uživatele, na základě kterých má dojít k autentizaci.
Dalším rozdílem je to, že metoda nevrací nějaký obecný výsledek, nýbrž při úspěšné auten-
tizaci již konkrétní identitu uživatele (třídu implementující rozhraní
Nette\Security\IIdentity). Za opačné situace (při neúspěšném ověření) by mělo dojít k vy-
volání příslušné výjimky Nette\Security\AuthenticationException. Způsob rozlišení chy-
bových stavů je tedy ponechán na vývojáři.
Z pohledu příchozího HTTP požadavku je uživatel reprezentován třídou
Nette\Security\User, která obsahuje metody pro přihlašování a odhlašování uživatele a rov-
něž jeho identitu získanou autentizací. Pro ukládání těchto dat slouží rozhraní
Nette\Security\IUserStorage, ve výchozím stavu je použito ukládání do session (třída
Nette\Http\UserStorage).
Ve srovnání s ostatními frameworky se Nette odlišuje svým postojem vůči autorizaci tím, že
pro něj deklaruje obecné rozhraní Nette\Security\IAuthorizator (tzv. autorizátor) a ACL
(třídu Nette\Security\Permission), již považuje za jednu z konkrétních možností jeho im-
plementace. Ze signatury autorizační metody IAuthorizator::isAllowed($role, $resource,
$privilege) vyplývá, že autorizace spočívá v ověření, že určitá role má/nemá specifikované
oprávnění k danému zdroji (ostatně, z tohoto principu vychází i ostatní frameworky). Třída
Permission z velké části vychází z Zend\Permission\Acl.
54 http://httpd.apache.org/docs/2.2/misc/password_encryptions.html
4 Porovnání PHP frameworků 73
Nette neobsahuje žádný kryptovací nástroj pro hešování hesel.
4.10.3 Phalcon
Oproti zbývajícím frameworkům Phalcon neobsahuje žádný předurčený autentizační systém
a uživatel tak není nijak identifikován. Pozornost tak lze věnovat jedině autorizaci a zabez-
pečení hesel.
Autorizační systém je založený na ACL, pro nějž bylo zavedeno rozhraní
Phalcon\Acl\AdapterInterface. Výchozím typem pro definici přístupových práv je třída
Phalcon\Acl\Adapter\Memory. Její název má za účel akcentovat fakt, že nakonfigurovaná
oprávnění jsou během doby vykonání skriptu uložena v operační paměti. Z podstaty věci se
však funkcionalita pochopitelně neliší od výše zmíněných Nette\Security\Permission
a Zend\Permissions\Acl\Acl, které co se týče názvu, abstrahují od způsoby uložení konfigu-
race.
Zásadním rozdílem, který ovlivňuje celkové zabezpečení aplikace je fakt, že adaptér Memory
ve výchozím stavu přístup k veškerým zdrojům povoluje. Pro změnu tohoto chování je za-
potřebí použít metodu AdapterInterface::setDefaultAction($defaultAccess), kde pro hod-
notu parametru $defaultAccess je vhodné použít předdefinovaných konstant:
Phalcon\Acl::DENY – zakázání přístupu,
Phalcon\Acl::ALLOW – povolení přístupu.
Pro hešování hesel je přímo určená metoda Phalcon\Security::hash($password,
$workFactor = NULL), která vnitřně používá bcrypt algoritmus stejně jako
např. Zend\Crypt\Password\Bcrypt. Pro zpětné porovnání hesla v syrové a zahešované po-
době slouží metoda Phalcon\Security::checkHash($password, $passwordHash,
$maxPasswordLength = null).
4.11 Lokalizace
4.11.1 Zend
Zend je ve svém přístupu k lokalizaci, resp. internacionalizaci ve srovnání s ostatními po-
rovnávanými frameworky jednoznačně nejobšírnější. Pro podporu univerzálního způsobu
lokalizace aplikace je zavedeno rozhraní Zend\I18n\Translator\TranslatorInterface dekla-
rující metody pro překlad zpráv:
4 Porovnání PHP frameworků 74
TranslatorInterface::translate($message, $textDomain = 'default', $locale =
NULL),
TranslatorInterface::translatePlural($singular, $plural, $number, $textDomain
= 'default', $locale = NULL).
Zdrojem přeložených zpráv může být jakákoliv třída implementující rozhraní
Zend\I18n\Translator\Loader\RemoteLoaderInterface, resp. Zend\I18n\Translator\Loa-
der\FileLoaderInterface (v případě, že se přepokládá, že se zdrojová data načítají ze sou-
boru).
Pro lokalizaci údajů týkajících se data a času, měny a číselných hodnot slouží pohledové
helpery nacházející se ve jmenném prostoru Zend\I18n\View\Helper (příslušné pluginy jsou
v šabloně k dispozici standardně automaticky).
Specifický účel plní tzv. filtry (jmenný prostor Zend\I18n\Filter), které slouží (s určitým
omezením55) k úpravě vstupního textového řetězce a validátory (jmenný prostor
Zend\I18n\Validator), které dokáží ověřit platnost např. data a času, číselné hodnoty či tele-
fonního čísla s ohledem na cílenou zemi (angl. locale).
Celkově vzato automaticky nejsou lokalizované žádné součásti frameworku, byť
např. v rámci pohledu lze snadno použít výchozích helperů, k lokalizaci musí dojít expli-
citně. Zejména při použití DI/service locatoru se lokalizace stává poměrně jednoduchou čin-
ností bez nutnosti psát vlastní lokalizační logiku.
4.11.2 Nette
O poznání volnější vztah k lokalizaci je patrný na první pohled, neboť jedinou součástí fra-
meworku, která s lokalizací souvisí, je rozhraní Nette\Localization\ITranslator (překla-
dač). Protože logika překládání může být poměrně různorodá, framework žádnou výchozí
implementaci nenabízí56.
Přesto framework s možností lokalizace „počítá“, a to tím, že např. jeho šablonový jazyk
Latte podporuje makro pro překlad textových zpráv. Rovněž implementace formulářové
komponenty, resp. jeho prvků je vytvořena tak, aby jej bylo možné snadno lokalizovat, a to
pouhým specifikováním konkrétního překladače pomocí metody
Nette\Forms\Form::setTranslator(Nette\Localization\ITranslator $translator = NULL).
55 Nejsou podporovány všechny druhy jazyků, viz http://framework.zend.com/ma-
nual/2.3/en/modules/zend.i18n.filters.html.
56 K dispozici jsou však volně šiřitelná rozšíření (např. http://addons.nette.org/#toc-locali-
zation).
4 Porovnání PHP frameworků 75
4.11.3 Phalcon
Phalcon jako jediný žádné lokalizační prostředky (třídy/rozhraní) nenabízí. Bylo-li by tomu
opačně, pak by tato skutečnost dle (Phalcon Team and contributors, 2014) vedla k pouhé
reduplikaci existujícího kódu. Nicméně na stejném místě je alespoň uvedena (ba přímo do-
poručena) alternativa v podobě specializované knihovny intl57, kterou koneckonců interně
využívá i Zend.
4.12 Využití cache
4.12.1 Zend
Systém umožňující používat cache je v Zend, jako je tomu i v mnoha jiných případech, re-
lativně nejsložitější58 a skládá se z následujících komponent:
Úložiště – rozhraní Zend\Cache\Storage\StorageInterface – třídy vycházející z to-
hoto rozhraní „jsou obálkami nad jejich skutečnými zdroji, které reprezentují (např.
souborový systém, paměť apod.)“ (Zend Technologies Ltd., 2014), konkrétní úlo-
žiště lze díky celkově dodávanému počtu typů poměrně jednoduše zaměnit za jiný,
Omezení/možnosti úložiště – třída Zend\Cache\Storage\Capabilities (např. mini-
mální, resp. maximální doba životnosti jednotlivých položek uložených v cache),
Rozšíření - Zend\Cache\Storage\Plugin\PluginInterface – jsou to „objekty,
za pomoci kterých lze ovlivnit chování konkrétního úložiště“ (Zend Technologies
Ltd., 2014),
Cache vzory – rozhraní Zend\Cache\Pattern\PatternInterface – představují
„konfigurovatelné objekty mající za cíl řešení častých výkonnostních problémů“
(Zend Technologies Ltd., 2014).
Jak je možné zpozorovat, Zend abstrahuje od existence jakéhosi „globálního“ správce ca-
che, nýbrž veškerá logika cache je zakomponována přímo v konkrétních adaptérech. Cache
vzory poskytují možnosti, jak cache využít v určitých specifických situacích (např. pro uklá-
dání návratových hodnot callbacků nebo za účelem zachycení výstupu PHP skriptu do ca-
che).
57 http://www.php.net/manual/en/intro.intl.php
58 Nejsložitější ve smyslu počtu komponent, které s cache souvisí.
4 Porovnání PHP frameworků 76
Základní princip práce s cache úložištěm znázorňuje Výpis 37. Vícenásobné přidání položky
pod stejným klíčem původní hodnotu nepřepíše, pro přepsání je nutné použít zvláštní metodu
StorageInterface::replaceItem($key, $value), resp. její alternativu pro přepsání několika
položek najednou StorageInterface::replaceItems(array $keyValuePairs).
Výpis 37: Příklad použití cache úložiště (Zdroj: autor)
use Zend\Cache\Storage\StorageInterface, Zend\Cache\Storage\Adapter\Filesystem, Zend\Cache\Storage\Adapter\FilesystemOptions; $options = new FilesystemOptions(); $options->setCacheDir('C:\temp'); $cache = new Filesystem($options); $cacheKey = 'myCacheKey'; if (!$cache->hasItem($cacheKey)) { $cache->addItem($cacheKey, 'some cached value'); } $value = $cache->getItem($cacheKey); var_dump($value); // vypíše // string(17) "some cached value" // Pro specifické případy, kdy chceme k hodnotě položky přičíst, resp. odečíst // určitou hodnotu slouží metoda StorageInterface::incrementItem($key, $value), // resp. StorageInterface::decrementItem($key, $value), přičemž položka nemusí // v cache existovat (bude automaticky vytvořena s hodnotou $value).
Zend v rámci jednoho úložiště neumožňuje ovlivnit parametry cache na úrovni jednotlivých
položek. Samostatné položce proto nelze nastavit např. dobu její životnosti. Možné je pouze
resetování její životnosti pomocí metody StorageInterface::touchItem($key), resp. Sto-
rageInterface::touchItems(array $keys). Zneplatnění položky lze dosáhnout jejím odstra-
něním z úložiště pomocí StorageInterface::removeItem($key),
resp. StorageInterface::removeItems(array $keys).
Výpis 38: Příklad použití cache vzoru Zend\Cache\Pattern\CallbackCache (Zdroj: autor)
use Zend\Cache\Pattern\CallbackCache, Zend\Cache\Pattern\PatternOptions; function myFunction() { // náročná operace ... } $cache = new CallbackCache();
4 Porovnání PHP frameworků 77
$cache->setOptions(new PatternOptions(array( 'storage' => 'memory', // nutné specifikovat typ úložiště ))); $cache->call(‘myFunction’); /////////////////////////////////////////////////////////// // anonymní funkce použít nelze (týká se všech frameworků), // dojde k vyvolání výjimky vyplívající z vlastností PHP $cache->call(function () { // náročná operace ... });
4.12.2 Nette
Struktura cache systému Nette se skládá z dvou částí:
1. Cache - třída Nette\Caching\Cache - zapouzdřující základní logiku cache voláním
příslušných metod úložiště (viz dále),
2. Úložiště - rozhraní Nette\Caching\IStorage – podobně jako v ostatní frameworky,
Nette podporuje vícero typů (součástí distribuce – jmenný prostor
Nette\Caching\Storages – je několik standardních typů: např. MemoryStorage,
FileStorage, atd.).
Třída Cache má v porovnání se svými ekvivalenty v jiných frameworcích, svá specifika,
protože podporuje přizpůsobení/změnu určitého chování na úrovni jednotlivých položek.
Rovněž je abstrahováno od rozdílu jejich přidávání a následného přepisování, pro obě akce
slouží jediná metoda Cache::save($key, $data, array $dependencies = NULL).
Výpis 39: Příklad použití Nette\Caching\Cache (Zdroj: autor)
use Nette\Caching\Cache, Nette\Caching\Storages\FileStorage; $fileStorage = new FileStorage('C:\temp'); $cache = new Cache($fileStorage); $cacheKey = 'myCacheKey'; // callback daný druhým parametrem metody Cache::load // slouží k prvotní inicializaci položky v případě, že neexistuje $value = $cache->load($cacheKey, function (&$dependencies) { // nastavení parametrů cache položky $dependencies = array( // automatická expirace za 30 minut Cache::EXPIRE => '+30 minutes',
4 Porovnání PHP frameworků 78
// automatický reset životnosti při nahrání položky Cache::SLIDING => TRUE, ); return 'my cached value'; }); var_dump($value); // vypíše: // string(15) "my cached value"
Manuální invalidace položky spočívá v jejím smazání metodou Cache::remove($key).
Nette podobně jako Zend umožňuje ukládat do cache i výsledky callback funkcí a ukládání
výstupu PHP, odlišuje se však tím, že pro tuto funkcionalitu nevymezuje žádnou další vrstvu
(obdobu Zend\Cache\Pattern\PatternInterface) a je součástí API třídy Cache, která navíc
kromě již zmíněných konfiguračních parametrů podporuje další reprezentované těmito kon-
stantami (Nette Foundation, 2014):
Cache::FILES – platnost položky může být odvislá na změně jednoho nebo více sou-
borů,
Cache::ITEMS – určuje závislost na platnosti jiných položek (v případě, že se zneplatní
jedna z nich, dojde k zneplatnění i této položky),
Cache::TAGS – přiřadí položce tag(y), usnadňující hromadnou invalidaci položek,
Cache::PRIORITY – slouží k hromadnému zneplatnění položek na základě jejich prio-
rity.
Nette poskytuje jednoduchou možnost, jak ovlivnit konkurenční chování související s uklá-
dáním položek do cache v případě několika souběžně běžících skriptů. V případě, že získání
zdrojových dat, resp. jejich uložení má být umožněno jedinému vláknu, pak lze jako hodnotu
položky uvést callback či anonymní funkci, jak ukazuje Výpis 40.
Výpis 40: Konkurenční chování ukládání cache položky (Zdroj: (Nette Foundation, 2014))
$result = $cache->save($key, function() { // nebo callback(...) return buildData(); // náročná operace });
4.12.3 Phalcon
Pojetí cache v frameworku Phalcon je vymezeno podobně jako u frameworku Nette dvěma
samostatnými částmi (Phalcon Team and contributors, 2014):
4 Porovnání PHP frameworků 79
1. Tzv. frontend – rozhraní Phalcon\Cache\FrontendInterface – konkrétní typy po-
dávají de facto informaci o původu dat, které mají být uloženy do cache a zároveň
definují způsob jejich případné modifikace, těsně před tím než má proběhnout fak-
tické uložení (stejně tak obráceně při čtení dat z tzv. backendu mohou být zdrojová
data transformována do konečné původní podoby),
2. Tzv. backend – rozhraní Phalcon\Cache\BackendInterface – jeho význam je
de facto totožný s tím, jaký mají cache úložiště v Zend a Nette.
Následující Výpis 41 demonstruje princip použití Phalcon cache. Stejně jako v systému
Nette lze položce nastavit max. dobu její životnosti. Avšak žádné další možnosti Phalcon již
nepodporuje.
Výpis 41: Příklad použití cache systému Phalcon (Zdroj: autor)
use Phalcon\Cache\Frontend\Data, Phalcon\Cache\Backend\File; $frontend = new Data(); $backend = new File($frontend, array( // cesta musí končit lomítkem, jinak dojde k chybné intepretaci cesty 'cacheDir' => 'C:\temp\\', )); $cacheKey = 'myCacheKey'; if (NULL === ($value = $backend->get($cacheKey))) { $value = 'my cached value'; $lifetime = 1800; // nastavení životnosti položky v sekundách $backend->save($cacheKey, $value, $lifetime); } var_dump($value); // invalidace položky $backend->delete($cacheKey); var_dump($backend->exists($cacheKey)); // script vypíše: // string(15) "my cached value" // bool(false)
4 Porovnání PHP frameworků 80
4.13 Ladění a zpracování chyb
4.13.1 Zend
Pro vizualizaci výjimek nabízí Zend možnost definovat samostatnou šablonu. Pomocí kon-
figurace pohledového manažera (třída Zend\Mvc\View\Http\ViewManager) lze nastavit cestu
k této šabloně. Chybové stavy související s nenalezením určité stránky je možné prezentovat
na samostatné šabloně. Standardizovaný způsob zobrazení chyb a s nimi souvisejících infor-
mací framework nenabízí. Bohužel, dojde-li k chybám, framework je ve výchozím stavu
sám nezachytí a patřičnou chybovou stránku nezobrazí (rozdíl mezi chybami a výjimkami).
Výpis 42: Příklad nastavení chybových šablon (Zdroj: autor)
$config = array( ‘view_manager’ => array( ‘exception_template’ => ‘error/index.phtml’, ‘not_found_template’ => ‘error/404.phtml’, ), );
Pro podporu ladění nabízí Zend samostatný balíček ZendDeveloperTools59, který však není
součástí standardní distribuce. Nástroj poskytuje základní informace mj. o době vykonání
skriptu (včetně rozlišení jednotlivých událostí), alokované paměti a informace o aktuálním
požadavku (řadič, akce a použitá šablona). Panel je složen z tzv. kolektorů (angl. collectors)
– tříd implementujících rozhraní ZendDeveloperTools\Collector\CollectorInterface.
Speciální pomůckou pro účely ladění je metoda Zend\Debug\Debug::dump($var, $label =
NULL, $echo = NULL), kterou lze vypisovat obsah dané proměnné. Framework ve srovnání
s použitím nativní funkce var_dump přináší přidanou hodnotu tím, že výpis je přehledněji
formátován a lze jej doplnit o volitelný popisek.
Není velkým překvapením, že Zend nabízí vlastní nástroj i pro logování. Jedná se o třídu
Zend\Log\Logger (dále jen logger) implementující rozhraní Zend\Log\LoggerInterface. Log-
ger pro svoji činnost vyžaduje přiřazení alespoň jednoho zapisovače (třída implementující
rozhraní Zend\Log\Writer\WriterInterface), jinak dojde při použití jedné z logovacích me-
tod k vyvolání výjimky (způsobeno „neprůhlednou“ definicí konstruktoru, které přijímá
jako jediný parametr konfigurační pole – ostatně jako četná řada dalších tříd frameworku).
Výpis 43: Příklad použití třídy Logger (Zdroj: autor)
use Zend\Log\Logger, Zend\Log\Writer\Stream;
59 https://github.com/zendframework/ZendDeveloperTools
4 Porovnání PHP frameworků 81
$var = array( 'foo' => 'bar', ); $writer = new Stream('C:\my_log.txt'); $logger = new Logger(); $logger->addWriter($writer); $logger->debug($var); $logger->info('some info message'); // obsah souboru C:\my_log.txt // 2014-04-26T17:05:43+02:00 DEBUG (7): array ('foo' => 'bar', ) // 2014-04-26T17:05:43+02:00 INFO (6): some info message
Možnosti loggeru jsou dále rozšířeny o tyto části (Zend Technologies Ltd., 2014):
filtry (rozhraní Zend\Log\Filter\FilterInterface) – zamezují logování určitých
hodnot (v závislosti na konkrétním použitém filtru),
formátovače (rozhraní Zend\Log\Formatter\FormatterInterface) – jejich úlohou je
provést volitelnou konverzi vstupní hodnoty do konečné podoby, která bude zalogo-
vána.
4.13.2 Nette
Uživatelsky definované zpracování výjimek ovlivňuje zejména třídní proměnná
Nette\Application::catchExceptions, jejíž hodnota by měla být typu boolean. Pokud je na-
stavena na hodnotu TRUE a dojde k vyvolání výjimky, která není zachycena, aplikační třída
automaticky přesměruje aplikační požadavek na tzv. chybový presenter (angl. Error Presen-
ter). Název presenteru, resp. jeho třídy je dán nastavením v konfiguračním souboru aplikace.
Ve výchozí akci presenteru, resp. vykreslovací části (metoda actionDefault($exception),
resp. renderDefault($exception)), probíhá zpracování samotné výjimky (typicky vykreslení
pohledu, kde šablony lze samozřejmě přizpůsobit různých typům výjimek).
Obdobou ZendDeveloperTools je nástroj Nette\Diagnostics\Debugger, který se však liší
svojí podporou pro vizualizaci výjimek i chyb (třída Nette\Diagnostics\BlueScreen). Jeho
aktivace se standardně projeví v zobrazení podobného ladícího panelu (reprezentován třídou
Nette\Diagnostics\Bar) a základní údaje, které poskytuje, se příliš neliší od jeho konkurenta
v podobě Zend. Z rozdílů lze jmenovat např. ten, že doba vykonání skriptu není rozdělena
dle jednotlivých událostí.
4 Porovnání PHP frameworků 82
Ladící panel jako celek se skládá z dalších samostatných panelů, které lze volitelně registro-
vat pomocí metody Bar::addPanel(Nette\Diagnostics\IBarPanel $panel, $id = NULL). Pří-
kladem, takového panelu budiž Nette\Application\Diagnostics\RoutingPanel, který
zobrazuje tabulkový výpis pravidel routování.
Třída Nette\Diagnostics\Dumper slouží k získání strukturovaného výpisu obsahu dané pro-
měnné (metoda Dumper::toHtml($var, array $options = NULL)). Pokud však je požadováno
informaci o proměnné rovnou vypsat na výstup, je možné použít buď statickou metodu
Debugger::dump($var, $return = FALSE) nebo využít její předdefinované zkratky formou
globální funkce dump($var).
Nejjednodušší způsob logování nabízí statická metoda Debugger::log($message, $priority
= self::INFO). Metoda je v podstatě zkratkou60 pro použití třídy Nette\Diagnostics\Dumper,
která nerozlišuje různé datové zapisovače (tak jak tomu bylo u frameworku Zend), ale výstup
je vždy reprezentován fyzickými soubory. Platí, že určením priority dojde k zalogování hod-
noty do souboru, jehož název je stejný jako hodnota tohoto parametru. Přípona .log logova-
cího souboru je přidána automaticky (např. info.log).
4.13.3 Phalcon
Phalcon nativně žádné zpracování výjimek např. pomocí definice zvláštních řadičů pro zpra-
cování chyby nepodporuje. Framework proces nijak neřeší a je na vývojáři, jakou cestu zvolí
(problém se týká i zpracování chyb).
Výpis 44: Příklad obsloužení výjimek v prostředí Phalcon pomocí události třídy Dispatcher
(Zdroj: (Thomas, 2014))
use Phalcon\Mvc\Dispatcher; $di = new \Phalcon\DI\FactoryDefault(); $di->set('dispatcher', function() use ($di) { $eventsManager = $di->getShared('eventsManager'); $eventsManager->attach( 'dispatch:beforeException', function($event, $dispatcher, $exception) { switch ($exception->getCode()) { case Dispatcher::EXCEPTION_HANDLER_NOT_FOUND: case Dispatcher::EXCEPTION_ACTION_NOT_FOUND: $dispatcher->forward(
60 Třídu by jinak bylo nutné při každém použití instanciovat (bez použití service locatoru/DI)
a nastavovat ji samostatně parametry. Takto je logger s globálními parametry nakonfi-
gurován s automaticky.
4 Porovnání PHP frameworků 83
array( 'controller' => 'error', 'action' => 'notFound', ) ); return false; default: $dispatcher->forward( array( 'controller' => 'error', 'action' => 'uncaughtException', ) ); return false; } } ); ... return $dispatcher; });
Phalcon\Debug je pomocným nástrojem pro vizualizaci nezachycených výjimek. Jeho akti-
vaci lze provést metodou Debug::listen($exceptions = NULL, $lowSeverity = NULL). Na roz-
díl od vizualizačního nástroje Nette, není výsledek zobrazen ve „full-screen“ podobě. Názvy
tříd frameworku vygenerovaného stacktrace jsou definovány jako odkazy přímo do doku-
mentace Phalcon, což může usnadnit vyhledání chyby (jejich konkrétní metody však již
„klikatelné“ nejsou).
Logovací mechanismus je podobný tomu z frameworku Zend, protože dochází k abstrakci
od konkrétního typu zapisovače dat. Skládá se z následujících dvou součástí (Phalcon Team
and contributors, 2014):
Adaptéry – rozhraní Phalcon\Logger\AdapterInterface – reprezentují typ zapiso-
vače dat,
Formátovače – rozhraní Phalcon\Logger\FormatterInterface – jejich smyslem je
umožnit korekci výsledného formátu logované zprávy.
4 Porovnání PHP frameworků 84
4.14 Rychlost
4.14.1 Celkové zpracování požadavku
Souhrnné výsledky rychlostního měření rozdělených do dvou fází představuje Tabulka 4,
Tabulka 5 a Tabulka 6. Jednotlivé údaje jsou rozděleny do dvou řádků, kde hodnoty
v řádku prvním vychází z nastavení PHP prostředí bez aktivovaného Zend OPcache (akce-
lerátor). V řádku druhém jsou naopak údaje, které byly zachyceny po aktivaci zmíněného
akcelerátoru. Kompletní zdrojová data jsou k nalezení v příloze.
Následuje stručná interpretace výsledků:
Výsledky potvrdili premisu, že Phalcon by měl být díky své architektuře rychlejší
než frameworky ostatní, a to dokonce několikanásobně při zachování celkově nej-
menší průměrné maximální paměťové náročnosti.
Phalcon rovněž dosahuje nejlepších výsledků v porovnání průměrného množství ma-
ximální alokované paměti, a to u obou fází napříč všemi třemi stránkami.
Nette dosahuje v důsledku inicializace cache v 1. fázi cca 1,2 – 1,5x horších výsledků
než Zend.
Markantního rozdílu bylo dosaženo v rámci měření 2. fáze rychlosti domovské
stránky Phalcon x Zend (Phalcon cca 50x rychlejší), resp. Phalcon x Nette (Phalcon
cca 25x rychlejší), viz Obrázek 2,
Měření navíc potvrdilo kladný účinek nasazení akcelerátoru, díky kterému došlo
u frameworků ke znatelnému navýšení rychlosti včetně snížení průměrné paměťové
náročnosti.
4 Porovnání PHP frameworků 85
Obrázek 2:
Graf porovnání rychlosti frameworků – domovská stránka – 2. fáze (bez použití akcelerátoru)
(Zdroj: autor)
Tabulka 4: Výsledky rychlostního měření – domovská stránka (Zdroj: autor)
Údaj Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
Průměrný
čas (ms)
x 219,88592 283,90365 113,33969 12,45232 4,30794
x 90,74519 175,80032 35,69744 14,28862 5,48899
Medián (ms) x 212,8886 278,71251 111,87804 11,15143 3,96204
x 79,20659 170,36295 35,49695 12,82942 5,70107
Směrodatná
odchylka
(ms)
x 26,85273 12,41409 5,35318 4,86426 1,20702
x 36,73862 15,28356 4,40114 4,43499 0,98182
Průměrná
alokovaná
paměť (MB)
x 3,79124 4,60024 2,9734 0,33914 0,3242
x 1,46605 1,58213 0,94095 0,215 0,19688
Medián
(MB)
x 3,79124 4,58135 2,9734 0,33916 0,3242
x 1,46605 1,58211 0,94052 0,21609 0,19661
Směrodatná
odchylka
(MB)
x 0 0,03041 0 0,00007 0
x 0,0002 0,00006 0,00135 0,00348 0,00086
0
50
100
150
200
250
300
1 2 3 4 5 6 7 8 9 10
Mili
seku
nd
y
Porovnání rychlosti - domovská stránka - 2. fáze(bez akcelerátoru)
Zend Nette Phalcon
4 Porovnání PHP frameworků 86
Tabulka 5: Výsledky rychlostního měření – seznam knih (Zdroj: autor)
Údaj Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
Průměrný
čas (ms)
x 211,23343 316,06431 118,22479 16,65163 9,38601
x 92,2147 206,88562 41,294 12,06989 12,25724
Medián (ms) x 206,25508 306,83649 118,88194 14,93192 9,07302
x 102,61011 200,80709 40,06934 11,68954 12,53903
Směrodatná
odchylka
(ms)
x 11,91252 42,6116 3,92038 4,41988 1,29622
x 19,73644 22,21896 6,26086 2,52908 1,05847
Průměrná
alokovaná
paměť (MB)
x 3,88046 4,66547 3,05564 0,38733 0,35126
x 1,49945 1,65449 1,00548 0,25081 0,21027
Medián
(MB)
x 3,88052 4,64574 3,05564 0,38735 0,35128
x 1,4995 1,64265 1,00536 0,25073 0,21002
Směrodatná
odchylka
(MB)
x 0,00019 0,03178 0,00001 0,00007 0,00007
x 0,00023 0,01906 0,00038 0,00025 0,00078
Tabulka 6: Výsledky rychlostního měření – detail knihy (Zdroj: autor)
Údaj Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
Průměrný
čas (ms)
x 213,0404 273,62309 118,22047 15,76769 8,62234
x 85,99448 336,04679 50,46511 18,20281 11,64963
Medián (ms) x 205,26004 273,68796 118,19494 15,93041 8,37886
x 86,94792 182,5316 48,28346 17,84301 11,307
Směrodatná
odchylka
(ms)
x 20,12999 5,41818 7,19631 2,96085 0,77037
x 16,99322 398,83537 9,48553 3,31359 1,62999
Průměrná
alokovaná
paměť (MB)
x 3,87743 4,60772 3,00503 0,37941 0,35125
x 1,49321 1,60245 0,95533 0,24096 0,20838
x 3,87752 4,60776 3,00503 0,37941 0,35127
4 Porovnání PHP frameworků 87
Údaj Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
Medián
(MB)
x 1,49317 1,60247 0,95501 0,24083 0,20814
Směrodatná
odchylka
(MB)
x 0,00026 0,00012 0 0 0,00008
x 0,00022 0,00007 0,00101 0,0004 0,00078
4.14.2 Výkonnost databázové vrstvy
Výsledky měření výkonnosti databázových vrstev poukázali na skutečnost, že rozdíl v pou-
žití 1. způsobu se znatelněji projevuje pouze v porovnání Zend a ostatních dvou frameworků.
Phalcon i Nette totiž dosahují téměř shodných průměrných výsledků, jak znázorňuje Obrá-
zek 3.
Výsledky (uvedené v tabulkách níže) potvrzují i nevyřčený předpoklad, že mezi použitím
1. a 2. způsobu (v rámci jednoho frameworku) existuje znatelný a dokonce několikanásobný
rozdíl.
Tabulka 7: Výsledky výkonnostního srovnání databázových vrstev – získání seznamu všech
knih (Zdroj: autor)
Měření Zend Nette Phalcon
1. způsob 2. způsob 1. způsob 2. způsob 1. způsob 2. způsob
Průměrný
čas (ms)
3,19853 15,28952 0,47038 12,58233 0,51193 23,89722
2,18172 6,47812 0,5249 3,27494 0,46475 24,41533
Medián (ms) 3,04842 14,23597 0,48447 12,62581 0,45657 23,19491
1,99759 6,28543 0,46897 3,35896 0,45097 24,04845
Směrodatná
odchylka
(ms)
0,33308 3,47677 0,04761 0,65967 0,15851 3,08323
0,44669 1,37453 0,14624 0,7386 0,05581 2,08445
Průměrná
alokovaná
paměť (MB)
4,02845 4,37919 2,75611 3,03149 0,35807 0,39423
1,48848 1,58971 0,85832 0,89954 0,2173 0,2525
Medián
(MB)
4,02861 4,37934 2,75617 3,03157 0,35811 0,39425
1,48853 1,58959 0,85835 0,89935 0,21735 0,25217
4 Porovnání PHP frameworků 88
Měření Zend Nette Phalcon
1. způsob 2. způsob 1. způsob 2. způsob 1. způsob 2. způsob
Směrodatná
odchylka
(MB)
0,00033 0,00031 0,00014 0,00018 0,00009 0,00006
0,00029 0,00034 0,00016 0,00074 0,0001 0,00079
Tabulka 8: Výsledky výkonnostního srovnání databázových vrstev – získání jedné knihy (Zdroj:
autor)
Měření Zend Nette Phalcon
1. způsob 2. způsob 1. způsob 2. způsob 1. způsob 2. způsob
Průměrný
čas (ms)
3,2578 15,07232 0,58215 11,78305 0,47679 23,3047
1,9635 7,23839 0,49081 2,89552 0,52748 24,07799
Medián (ms) 3,23963 15,203 0,56005 11,54006 0,46647 23,73493
1,96397 7,05647 0,48351 2,94459 0,43941 24,36805
Směrodatná
odchylka
(ms)
0,22029 0,86419 0,12979 1,29797 0,04376 2,51639
0,12979 0,81238 0,06502 0,64249 0,16183 1,64055
Průměrná
alokovaná
paměť (MB)
4,02995 4,40865 2,7466 3,03223 0,35835 0,39839
1,48974 1,60344 0,84771 0,89668 0,21423 0,25535
Medián
(MB)
4,03003 4,40874 2,74663 3,03224 0,35837 0,39841
1,48968 1,60329 0,8477 0,89672 0,21426 0,25537
Směrodatná
odchylka
(MB)
0,00025 0,00028 0,0001 0,00005 0,00007 0,00007
0,00026 0,00045 0,00008 0,00012 0,00007 0,00007
4 Porovnání PHP frameworků 89
Obrázek 3:
Výsledky výkonnostního měření databázové vrstvy – získání seznamu všech knih 1. způsobem
(bez akcelerátoru) Zdroj: autor)
Obrázek 4:
Výsledky rychlostního měření databázové vrstvy – získání seznamu všech knih 2. způsobem
(bez akcelerátoru) (Zdroj: autor)
0
0.5
1
1.5
2
2.5
3
3.5
4
1 2 3 4 5 6 7 8 9 10
Mili
seku
nd
y
Získání seznamu všech knih 1. způsobem(bez akcelerátoru)
Zend Nette Phalcon
0
5
10
15
20
25
30
35
1 2 3 4 5 6 7 8 9 10
Mili
seku
nd
y
Získání seznamu všech knih 2. způsobem(bez akcelerátoru)
Zend Nette Phalcon
4 Porovnání PHP frameworků 90
Obrázek 5:
Výsledky rychlostního měření databázové vrstvy – získání seznamu všech knih 2. způsobem
(se zapnutým akcelerátorem) (Zdroj: autor)
Na první pohled je zřejmé, že Phalcon je na tom z rychlostního pohledu (pravděpodobně
kvůli vlastnímu „vysoko-úrovňovému“ dotazovacímu jazyku, který je vnitřně komplikova-
nější a náročnější než ostatní) relativně nejhůře. Na druhou stranu, jeho průměrná maximální
paměťová náročnost zůstává opět nejnižší.
Mediánové i průměrné hodnoty zjištěné bez zapnutého akcelerátoru popisující 2. způsob
získání seznamu všech knih z databáze (dále se má na mysli srovnání Zend a Nette) jsou si
relativně blízké (viz Obrázek 4), což naznačuje, že mezi nimi není znatelného výkonnostního
(rychlostního) rozdílu. Naopak v případě aktivovaného akcelerátoru (Obrázek 5) se tyto hod-
noty již liší poměrně více (Nette cca 2x rychlejší než Zend), což nasvědčuje tomu, že efekt
optimalizace se u frameworků projevil různou měrou. Za předpokladu, že se oba soubory
hodnot řídí normálním rozdělením a rozptyly obou základních souborů nejsou známy, mů-
žeme tyto dvě hypotézy ověřit statistickým t-testem61:
1. Získání všech knih 2. způsobem bez akcelerátoru:
a. Nulová hypotéza H0: 𝜇1. 𝑧𝑝ů𝑠𝑜𝑏 = 𝜇2. 𝑧𝑝ů𝑠𝑜𝑏 … výkonnost 2. způsobu reali-
zovaného ve frameworcích Zend a Nette se neliší,
b. Alternativní hypotéza H1: 𝜇1. 𝑧𝑝ů𝑠𝑜𝑏 ≠ 𝜇2. 𝑧𝑝ů𝑠𝑜𝑏 … výkonnostně se imple-
mentace v obou frameworcích významně liší,
61 Postup vychází z (Hindls, 2007), resp. (Studentův t-test a F-test, 2010).
0
5
10
15
20
25
30
1 2 3 4 5 6 7 8 9 10
Mili
seku
nd
y
Získání seznamu všech knih 2. způsobem(se zapnutým akcelerátorem)
Zend Nette Phalcon
4 Porovnání PHP frameworků 91
c. Testové kritérium: 𝑡 =𝑥1̅̅̅̅ −𝑥2̅̅̅̅
√𝑠1
2
𝑛1+
𝑠22
𝑛2
=15,28952−12,58233
√3,476772
10+
0,659672
10
≅ −2,419,
d. Kritický obor:
i. Rozdělení t s v stupni volnosti,
ii. Počet stupňů volnosti: 𝑣 =(
𝑠12
𝑛1+
𝑠22
𝑛2)
2
(𝑠1
2
𝑛1)
21
𝑛1+1+(
𝑠22
𝑛2)
21
𝑛2+1
− 2 =
(3,476772
10+
0,659672
10)
2
(3,476772
10)
21
10+1+(
0,659672
10)
21
10+1
− 2 ≅ 9,771 ≅ 10
iii. 𝑊 = {|𝑡| ≥ 𝑡1−𝛼2⁄ (10)}, hladina významnosti … α = 0,05 =>
𝑊 = {|𝑡| ≥ 2,228},
e. |−2,419| ≥ 2,228 => na zvolené 5% hladině významnosti zamítáme nulo-
vou hypotézu, u frameworků Zend a Nette byl prokázán statisticky významný
výkonnostní rozdíl v použití objektově orientovaného způsobu tvorby,
resp. položení databázového dotazu při vypnutém akcelerátoru.
2. Získání všech knih 2. způsobem se zapnutým akcelerátorem:
a. Nulová hypotéza H0: 𝜇1. 𝑧𝑝ů𝑠𝑜𝑏 = 𝜇2. 𝑧𝑝ů𝑠𝑜𝑏 … výkonnost 2. způsobu reali-
zovaného ve frameworcích Zend a Nette se zapnutým akcelerátorem se neliší,
b. Alternativní hypotéza H1: 𝜇1. 𝑧𝑝ů𝑠𝑜𝑏 ≠ 𝜇2. 𝑧𝑝ů𝑠𝑜𝑏 … výkonnostně se imple-
mentace v obou frameworcích při zapnutém akcelerátoru významně liší,
c. Testové kritérium: 𝑡 =𝑥1̅̅̅̅ −𝑥2̅̅̅̅
√𝑠1
2
𝑛1+
𝑠22
𝑛2
=6,47812−3,27494
√1,374532
10+
0,73862
10
≅ 7,168,
d. Kritický obor:
i. Rozdělení t s v stupni volnosti,
ii. Počet stupňů volnosti: 𝑣 =(
𝑠12
𝑛1+
𝑠22
𝑛2)
2
(𝑠1
2
𝑛1)
21
𝑛1+1+(
𝑠22
𝑛2)
21
𝑛2+1
− 2 =
(1,374532
10+
0,73862
10)
2
(1,374532
10)
21
10+1+(
0,73862
10)
21
10+1
− 2 ≅ 14,863 ≅ 15
iii. 𝑊 = {|𝑡| ≥ 𝑡1−𝛼2⁄ (15)}, hladina významnosti … α = 0,05 =>
𝑊 = {|𝑡| ≥ 2,131},
4 Porovnání PHP frameworků 92
e. |7,168| ≥ 2,131 => na zvolené 5% hladině významnosti zamítáme nulovou
hypotézu, při zapnutém akcelerátoru byl u frameworků Zend a Nette proká-
zán statisticky významný výkonnostní rozdíl použití objektově orientova-
ného způsobu tvorby a položení databázového dotazu.
Na základě obou dvou statistických testů bylo s 5% mírou pravděpodobnosti chyby zjištěno,
že mezi použitím 2. způsobu ve frameworcích Zend a Nette je statisticky významný výkon-
ností rozdíl. Ukázalo se tak, že prvotní interpretace srovnání mediánových, resp. průměrných
hodnot (bez zapnutého akcelerátoru) byla mylná. Podobně by se dalo postupovat i ve srov-
nání ostatních údajů.
4.15 Ostatní
Následující část shrnuje další faktory související s potenciálním výběrem a použitím zvole-
ných frameworků.
4.15.1 Licenční omezení
Všechny frameworky jsou k dispozici pod tzv. New BSD License62. Software vydaný
pod touto licencí je při zachování určitých podmínek volně šiřitelný (The Open Source
Initiative, nedatováno):
1. Redistribuovaný zdrojový kód musí obsahovat znění licenčního omezení.
2. Redistribuce v binární podobě musí rovněž obsahovat znění licenčního omezení.
3. Jména vlastníků autorských práv (včetně ostatních přispěvatelů) nesmí být bez spe-
ciálního souhlasu použita za účelem reklamy produktu odvozeného z tohoto soft-
waru.
Jedinou výjimkou je Nette, které nabízí možnost zvolit si z dvou možností licencování.
Tabulka 9: Licenční omezení frameworků (Zdroj: (Zend Technologies Ltd., 2014), (Nette
Foundation, 2014), (Phalcon Framework Team, 2014))
Zend Nette Phalcon
Licence New BSD License New BSD License New BSD License
62 Šablona licenčního ujednání je k dispozici na http://opensource.org/licenses/BSD-3-
Clause.
4 Porovnání PHP frameworků 93
GNU General Public
License (verze 2/3)
4.15.2 Dokumentace
Dokumentace všech tří frameworků je k dispozici online (v anglickém jazyce) na oficiálních
stránkách a obsahuje i část věnující se API. Součástí dokumentace je alespoň jedna ukázka
jednoduché aplikace. V případě Zend a Nette lze pak přímo na oficiálních stránkách nalézt
i tzv. video-tutoriály. Dokumentace Nette je jako jediná k dispozici i v češtině.
Každý framework nabízí možnost stažení oficiální API dokumentace pro tzv. offline63 pou-
žití. Při srovnání těchto verzí lze za relativně nejméně pohodlnou označit variantu Phalcon,
protože kompletní dokumentace není rozdělena na samostatné stránky, nýbrž vše je součástí
jediné a poměrně dlouhé HTML stránky, jejíž načtení určitou chvíli trvá. Podobně je na tom
i Zend, který však v základním přehledu neuvádí i jednotlivé metody rozhraní a tříd (tyto
údaje jsou zobrazovány až v detailu dané položky).
Existence knižních publikací věnujících se danému frameworku pravděpodobně nepatří
mezi ty nejdůležitější faktory. Dokumentace aktivně vyvíjeného frameworku má tendenci
rychle zastarávat, přesto existují příklady frameworků, o kterých byly vydány knižní publi-
kace. Jmenovitě se jedná o frameworky Zend a Phalcon64.
Tabulka 10: Porovnání dalších faktorů spojených s dokumentací frameworků (Zdroj: autor)
Zend Nette Phalcon
CZ dokumentace Ne Ano Ne
Offline API Ano Ano Ano
Knižní publikace Ano Ne Ano
4.15.3 Komunita spojená s frameworkem
Vyjdeme-li z veřejně dostupných dat znázorněných v tabulce níže, pak komunita spojená
s frameworkem Zend je v absolutním měřítku jednoznačně nejširší. Jako referenční komu-
nitní servery byly stanoveny:
63 Myšleno bez nutnosti internetového připojení – dokumentaci je možné používat z lokál-
ního disku.
64 V době psaní práce byl pravděpodobně jediným vydaným titulem Getting Started with
Phalcon (Stephan A. Miller, 2014).
4 Porovnání PHP frameworků 94
1. GitHub (http://www.github.com),
2. StackOverflow (www.stackoverflow.com).
V případě GitHub byly agregované hodnoty pro snížení vlivu faktoru času upraveny dle
vzorce: 𝑢𝑝𝑟𝑎𝑣𝑒𝑛ý ú𝑑𝑎𝑗 =ℎ𝑜𝑑𝑛𝑜𝑡𝑎 𝑠𝑙𝑒𝑑𝑜𝑣𝑎𝑛éℎ𝑜 ú𝑑𝑎𝑗𝑒
𝑠𝑡áří 𝑟𝑒𝑝𝑜𝑠𝑖𝑡ář𝑒 𝑣𝑒 𝑑𝑛𝑒𝑐ℎ. V tabulce jsou upravené hodnoty uve-
dené v závorce za původním údajem. Intepretace těchto údajů má samozřejmě celou řadu
omezení, neboť není brána v potaz doba, po kterou byl framework k dispozici např. z jiného
zdroje.
Interpretovat upravené hodnoty můžeme např. takto:
Ačkoliv absolutní hodnoty Zend hovoří o jeho dominanci, z upravených hodnot tý-
kajících se počtu sledování změn repositáře dosahuje relativně horšího výsledku než
Phalcon.
Poměr tzv. pull repositářových požadavků frameworků Nette i Phalcon je přibližně
stejný i přesto, že repositář Phalcon je cca 3,5x mladší, což naznačuje relativně vyšší
zájem o tento framework.
Zájem o tvorbu vlastních repositářů založených na původních (angl. forks) je nej-
vyšší v případě Zend, nejnižší je naopak u Nette (cca 15x nižší v porovnání s Zend),
u Phalcon je pak přibližně 3x nižší a zároveň asi 6x vyšší než u Nette.
Tabulka 11: Absolutní srovnání v rámci komunitních serverů ke dni 28. 4. 2014 (Zdroj: autor)
Zend Nette Phalcon
GitHub – stáří repositáře (ve dnech) 1829 3019 842
GitHub Forks 2731 (1,49) 271 (0,09) 444 (0,53)
GitHub Pull Requests 78 (0,04) 55 (0,02) 13 (0,02)
GitHub Watches 557 (0,30) 118 (0,04) 391 (0,46)
StackOverflow – otagované otázky 35 638 / 713465 x66 358
StackOverflow – počet výsledků dle
vyhledávání
17 326 / 450367 161 834
65 Údaj před lomítkem udává počet výsledků na základě obecně zadaného tagu zend, údaj
za pak zend-framework-2.
66 Tag pro Nette neexistuje.
67 Údaj před lomítkem udává počet výsledků na základě obecně zadaného tagu zend, údaj
za pak zend 2.
4 Porovnání PHP frameworků 95
4.15.4 Počet pracovních nabídek
Tabulka 12 ukazuje aktuální počet pracovních nabídek několika vybraných online pracov-
ních portálů z řad českých i zahraničních zástupců, vyhledaných na základě odpovídajícího
klíčového slova. Platí-li předpoklad, že lze z výsledků usuzovat na relativní známost frame-
worku, pak lze konstatovat, že Nette je v zahraničí prakticky neznámý. Nepatrně lépe je
na tom Phalcon, který ačkoliv je daleko mladší, na jednom z portálů bylo nalezeno několik
relevantních nabídek. V absolutním měřítku Zend zůstává jednoznačně na přední pozici jako
nejznámější framework vůbec.
Výsledky mohou podpořit názor, že velkou měrou se na míře jejich oblíbenosti podílí to, zda
se jedná o tuzemský nebo zahraniční framework, resp. pracovní portál.
Klíčová slova zastupující jednotlivé frameworky byly zvoleny následovně (u všech je abs-
trahováno od požadované verze):
Zend – zend,
Nette – nette,
Phalcon – phalcon.
Tabulka 12: Aktuální počet nabídek na pracovních portálech – stav ke dni 3. 5. 2014 (Zdroj:
autor)
Pracovní portál Zend Nette Phalcon
www.jobs.cz (CZ) 17 22 0
www.prace.cz (CZ) 11 10 0
www.monster.com (US) 11 0 0
www.indeed.com (US) 964 068 15
www.elance.com (US) 1342 8 14
4.15.5 Existující rozšíření
Kvalitu a oblíbenost frameworku ovlivňují i možnosti jeho rozšíření. Existence oficiální da-
tabáze uživatelsky definovaných rozšíření znázorňuje Tabulka 13. Jejich největší počet lze
nalézt pro framework Zend. Phalcon naopak žádnou oficiální databázi volně dostupných
68 Ve skutečnosti vyhledávač zobrazil výsledky 4, ale všechny byly očividně nerelevantní.
4 Porovnání PHP frameworků 96
rozšíření nenabízí. Položka kategorizace znamená, zdali jsou rozšíření v rámci databáze roz-
dělena do kategorií (např. na vizuální/nevizuální komponenty apod.).
Tabulka 13: Dostupnost rozšíření (Zdroj: autor)
Zend Nette Phalcon
Databáze rozšíření Ano Ano Ne
Kategorizace Ne Ano x
5 Závěr 97
5 Závěr Náplní této práce bylo porovnání tří vybraných PHP frameworků na základě předem stano-
vených kritérií. V první části byly nejprve vymezeny nejdůležitější obecné pojmy související
s vývojem webových aplikací za pomocí frameworků. Vzhledem k tomu, že se této proble-
matice věnovalo již několik autorů, další související termíny byly zmíněny až v průběhu
práce. Okrajově byly zmíněny způsoby hodnocení oblíbenosti jednotlivých frameworků
např. za pomocí statistik vyhledávanosti v různých komunitních serverech a internetových
vyhledávačích. Některých přístupů bylo pak posléze využito v druhé stěžejní části práce.
Jednotlivé problémové oblasti, které sloužily jako podklad pro porovnání frameworků byly
popsány v kapitole 3.3. Snahou bylo vyjmenovat jednotlivá kritéria tak, aby na sebe pokud
možno logicky navazovala. Ne vždy se podařilo tomuto ohledu dostát, protože problematika
je velmi komplexního charakteru. Pro porovnání v některých oblastech byly definovány vý-
zkumné otázky, na které bylo později v průběhu textu odpovězeno (ne nutně vždy expli-
citně).
V kapitole 4 byly frameworky již charakterizovány vždy v rámci jedné vybrané oblasti
a každý zvlášť v pořadí Zend, Nette, Phalcon. Výjimkou z tohoto pravidla byla zejména
podkapitola 4.14 věnující se rychlosti frameworků a podkapitola poslední (4.15) shrnující
některé ostatní faktory související s frameworkem, jako je jejich relativní popularita na zná-
mých komunitních serverech GitHub a StackOverflow a stejně tak i podmínky licencování
atd.
Teoreticko-praktická část byla koncipována tak, aby pokud možno vynikly zásadní rozdíly
v pojetí zmíněných problémových oblastí napříč všemi frameworky. Toho by mělo být do-
saženo tím, že kromě popisu API je text doprovázen i ukázkami kódu, z nichž část je čerpána
z oficiální dokumentace a část z vlastních příkladů autora. Samozřejmě, že nebylo vždy
možné v rámci výkladu postihnout všechny možné případy, filozofie frameworků, které jsou
v práci představeny, by ale měla být zřejmá (např. Zend razící pravidlo „obšírné“ konfigu-
race, Nette kladoucí důraz na jednoduchost a Phalcon, který díky své architektuře vyniká
svoji rychlostí).
Má-li být závěrem opětovně zmíněn cíl práce stanovený v úvodu práce – představení frame-
worků a popis jejich použitelnosti z pohledu vývojáře – pak se domnívám, že tohoto primár-
ního cíle bylo dosaženo a práce tak může čtenáři být onou počáteční motivací pro další
studium alespoň některého z nich (případně naopak).
Z návrhů na rozšíření prohlubující poznatky o frameworcích je možné uvést např. práce po-
pisující určitý nadstavbový framework, který vychází z některého z uvedených frameworků
s doprovodným popisem jeho nasazení v praxi. Jako hodnotné by se mohlo ukázat i hlubší
porovnání databázových vrstev s knihovnami 3. stran, které nejsou součástí žádného frame-
worku. V souvislosti s frameworkem Phalcon by pak mohlo být rovněž zajímavé jeho srov-
nání s jinými platformami (jmenovitě ASP. NET), zejména za účelem porovnání rychlosti.
Terminologický slovník 98
Terminologický slovník Termín Zkratka Význam [zdroj]
Access Control List ACL Systém řízení přístupu na základě definovaných rolí a pra-
videl. (Zdroj: autor)
Aplikační rozhraní API Sada veřejné dostupných funkcí a tříd, resp. jejich metod.
(Zdroj: autor)
Autoloading x Mechanismus PHP umožňující dodatečné nahrávání zdro-
jových souborů obsahující deklarace požadovaných tříd
a rozhraní. (Zdroj: autor)
Cache x Speciální typ datového úložiště relativně krátkodobého
charakteru určený k ukládání relativně stálých neměnných
dat za účelem navýšení rychlosti aplikace. (Zdroj: autor)
Callback x Schéma používané v událostně-řízených programech, kde
program registruje určité procedury (obslužné funkce)
k obsloužení určité události. Program takovou funkci ne-
volá přímo, nýbrž je volána systémem za běhu a obvykle
jsou jí předány dodatečné argumenty popisující událost.
(Zdroj: (Howe, 2003))
Composer x Nástroj pro správu externích závislostí pro jazyk PHP.
(Zdroj: (Adermann & Boggiano, 2011))
Dependency Injection DI Paradigma OOP návrhu, jehož cílem je odstranění skry-
tých závislostí zavedením tzv. principu obráceného řízení.
(Zdroj: autor)
Dependency Injection
Container
DI
Container
Místo (objekt), který slouží k centralizované správě vytvá-
řených instancí. (Zdroj: autor)
Data Definition
Language
DDL Podmnožina jazyka SQL určená k definici/popisu struk-
tury dat. (Zdroj: autor)
Data Manipulation
Language
DML Podmnožina jazyka SQL určená k manipulaci s daty (vy-
tváření, úprava, mazání, výběr). (Zdroj: autor)
Extensible Markup
Language
XML Sémantický značkovací jazyk určený převážně k přenosu
dat v textové podobě. (Zdroj: (Refsnes Data, 2014))
Fasáda (angl. facade) x Druh „vysoko-úrovňového“ API mající za cíl zjednodušit
práci s několika dalšími podsystémy (zjednodušující
obálka nad relativně složitým API). (Zdroj:
(SourceMaking, nedatováno))
First In First Out FIFO Zpracování požadavků od nejstaršího po nejnovější.
(Zdroj: (Rouse, 2005))
Terminologický slovník 99
Termín Zkratka Význam [zdroj]
GET x Typ HTTP požadavku, při kterém jsou odesílaná data pře-
nášena prostřednictvím URL. (Zdroj: (Refsnes Data,
2014))
Helper x Označení pro pomocnou funkci/třídu/metodu. (Zdroj: au-
tor)
Hešování x Technika konverze vstupního řetězce za pomocí speciál-
ního algoritmu do takové podoby, která je z bezpečnost-
ních důvodů vhodnější k zaznamenávání. (Zdroj: autor)
The Hypertext Transfer
Protocol
HTTP Bezestavový aplikační protokol umožňující komunikaci
mezi klientem a serverem. (Zdroj: (Refsnes Data, 2014))
HyperText Markup
Language
HTML Značkovací jazyk určený primárně pro popis (tvorbu) we-
bových stránek. (Zdroj: (Refsnes Data, 2014))
Kolace (angl. collation) x Způsob porovnávání textových řetězců v databází,
resp. tabulkových sloupcích, který ovlivňuje řazení hodnot
v nich obsažených. (Zdroj: autor)
Last In First Out LIFO Způsob zpracování požadavků, při kterém jsou zpracová-
vány zprvu požadavky nejaktuálnější (od posledně přida-
ného) až postupně po požadavek nejstarší (nejdříve
přidaný). (Zdroj: (Rouse, 2005))
Logování x Technika zaznamenávání určitých dat typicky za účelem
jejich pozdější analýzy nebo ladění. (Zdroj: autor)
Magic methods x Magické metody představují druh nativních třídních me-
tod se speciálním významem. (Zdroj: autor)
Model View Controller MVC Obecný architektonický návrhový vzor, ve kterém dochází
k rozdělení aplikace na tři relativně nezávislé části (pro-
blémové oblasti): model, pohled a řadič. (Zdroj: autor)
Návrhový vzor x Jistý druh „osvědčeného“ způsobu řešení určitého rela-
tivně často se opakujícího se problému. (Zdroj: autor)
PHP: Hypertext
Preprocessor
PHP Dynamický interpretovaný skriptovací jazyk, který je ur-
čen obzvláště k vývoji webových stránek a aplikací. (The
PHP Group, 2014)
POST x Typ HTTP požadavku, při kterém jsou odesílaná data sou-
částí jeho těla. (Zdroj: (Refsnes Data, 2014))
PSR-0 x Standard pro použití autoloadingu zahrnující pravidla
pro mapování tříd a rozhraní, resp. umístění souborů obsa-
hující jejich deklaraci v návaznosti na souborový systém.
(Zdroj: autor)
Terminologický slovník 100
Termín Zkratka Význam [zdroj]
Service locator x Objekt, jenž má umožnit lokalizaci (získání) externích zá-
vislosti. (Zdroj: (Grudl, DI versus Service Locator, 2012))
Session hijacking x Bezpečnostní hrozba spočívající v odcizení uživatelské
session úspěšným získáním/vygenerováním existující ses-
sion ID. (Zdroj: (Imperva, 2014))
Structured Query
Language
SQL Strukturovaný dotazovací jazyk určený k dotazování se do
databází na něm postavených. (Zdroj: autor)
Type Hinting x Vlastnost přidaná v PHP 5, díky které argumenty funkce
musí být specifikovaných typů (instance třídy a instance
třídy implementující určité rozhraní, pole a od verze PHP
5.4 i tzv. callable typ (callback)). (Zdroj: (The PHP
Group, nedatováno))
Uniform Resource
Identifier
URI Řetězec znaků identifikující názvy a zdroje v prostředí In-
ternetu. (Zdroj: (Janalta Interactive Inc., 2014))
Seznam literatury 101
Seznam literatury [1] Adermann, N., & Boggiano, J. (2011). Getting Started. Získáno 3. 5 2014, z
Composer: https://getcomposer.org/doc/00-intro.md
[2] Application Framework. (2014). Získáno 15. 3 2014, z Techopedia - Where IT and
Business Meet: http://www.techopedia.com/definition/6005/application-framework
[3] Bose, D. (nedatováno). COMPONENT BASED DEVELOPMENT. Získáno 16. 3 2014,
z APPLICATION IN SOFTWARE ENGINEERING:
http://arxiv.org/ftp/arxiv/papers/1011/1011.2163.pdf
[4] Design Patterns. (2014). Získáno 15. 3 2014, z MSDN – the Microsoft Developer
Network: http://msdn.microsoft.com/en-us/library/ff649977.aspx
[5] Dictionary.com. (nedatováno). database. Získáno 7. 5 2014, z Dictionary.com - Free
Online English Dictionary: http://dictionary.reference.com/browse/database
[6] Dispatching Controllers. (2014). Získáno 5. 4 2014, z Phalcon 1.3.0 documentation:
http://docs.phalconphp.com/en/latest/reference/dispatching.html
[7] Eini, O. (11 2006). Inversion of Control and Dependency Injection: Working with
Windsor Container. Získáno 16. 3 2014, z MSDN – the Microsoft Developer
Network: http://msdn.microsoft.com/en-us/library/aa973811.aspx
[8] Fowler, M. (23. 1 2004). Inversion of Control Containers and the Dependency
Injection pattern. Získáno 16. 3 2014, z Martin Fowler:
http://martinfowler.com/articles/injection.html
[9] Fowler, M., Rice, D., Foemmel, M., Hieatt, E., Mee, R., & Staffort, R. (2002). Model
View Controller. V Patterns of Enterprise Application Architecture (str. 286).
Addison Wesley.
[10] framework - definition of framework by Macmillan Dictionary. (2014). Získáno 15. 3
2014, z Macmillan Dictionary and Thesaurus: Free English Dictionary Online:
http://www.macmillandictionary.com/dictionary/british/framework
[11] Frank, J. (2013). Porovnání frameworků Grails(Groovy) a Nette(PHP) pro rychlý
vývoj webových aplikaci.
[12] Freeman, E., Freeman, E., Sierra, K., & Bates, B. (2004). The power of Loose
Coupling. V Head First Design Patterns (str. 72). Sebastopol: O'Reilly Media, Inc.
[13] Grudl, D. (7. 5 2012). DI a předávání závislostí. Získáno 16. 3 2014, z phpFashion:
http://phpfashion.com/di-a-predavani-zavislosti#toc-konstruktor-hell
[14] Grudl, D. (14. 3 2012). DI versus Service Locator. Získáno 2. 5 2014, z phpFashion:
http://phpfashion.com/di-versus-service-locator
[15] Hindls, R. (2007). V R. Hindls, S. Hronová, J. Seger, & J. Fischer, Statistika pro
ekonomy (8. vydání. vyd., stránky 146-148). Praha: Professional Publishing. Získáno
10. 5 2014
[16] Howe, D. (13. 7 2003). callback. Získáno 3. 5 2014, z Dictionary.com:
http://dictionary.reference.com/browse/callback
Seznam literatury 102
[17] IBM Corporation. (2010). Compiled versus interpreted languages. Získáno 9. 3 2014,
z IBM:
http://publib.boulder.ibm.com/infocenter/zos/basics/index.jsp?topic=/com.ibm.zos.zap
pldev/zappldev_85.htm
[18] Imperva. (2014). Session Hijacking. Získáno 2. 5 2014, z Imperva - Data Center
Security Solutions:
http://www.imperva.com/Resources/Glossary?term=session_hijacking
[19] Internet Engineering Task Force. (4 2011). HTTP State Management Mechanism.
Získáno 7. 5 2014, z IETF Tools: http://tools.ietf.org/html/rfc6265
[20] Introduction to the MVC Layer. (2014). Získáno 30. 3 2014, z Zend Framework 2
2.3.0 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.mvc.intro.html
[21] Janalta Interactive Inc. (2014). Uniform Resource Identifier (URI). Získáno 2. 5 2014,
z Techopedia - Where IT and Business Meet:
http://www.techopedia.com/definition/25550/uniform-resource-identifier-uri
[22] Korop, P. (20. 11 2013). TOP 6 most popular PHP frameworks of 2013. Získáno 15. 3
2014, z WebCoderPro - web-development, PHP, Wordpress:
http://webcoderpro.com/blog/top-6-most-popular-php-frameworks-of-2013/
[23] Koščo, J. (2013). Porovnanie PHP frameworkov Symfony 2 a Zend Framework 2.
[24] Kosek, J. (1999). Formuláře. V PHP Tvorba interaktivních internetových aplikací (str.
93). Grada Publishing, spol. s r.o.
[25] Křižan, O. (2010). Vybrané frameworky pro vývoj aplikací v PHP a jejich srovnání.
Načteno z ISIS:
https://isis.vse.cz/auth/zp/portal_zp.pl?prehled=vyhledavani;podrobnosti=78307;down
load_prace=1;lang=cz
[26] Kutišová, M. (2013). Zend Framework.
[27] Lecky-Thompson, E., Nowicki, S. D., & Myer, T. (2009). Logging and Debugging -
Creating a Logging Mechanism. V Professional PHP6 (str. 201). Indianapolis: Wiley
Publishing, Inc.
[28] Microsoft. (2014). Localization. Získáno 22. 3 2014, z MSDN Developer Network:
http://msdn.microsoft.com/en-us/library/5839we2z%28v=vs.110%29.aspx
[29] Nette Foundation. (2014). Auto-loading tříd. Získáno 29. 4 2014, z Nette Framework:
http://doc.nette.org/cs/2.1/auto-loading
[30] Nette Foundation. (2014). Cache. Získáno 25. 4 2014, z Nette Framework:
http://doc.nette.org/cs/2.1/caching
[31] Nette Foundation. (2014). Class CliRouter. Získáno 5. 4 2014, z Nette Framework
2.1.2 API: http://api.nette.org/2.1.2/Nette.Application.Routers.CliRouter.html
[32] Nette Foundation. (2014). File Application/UI/Presenter.php. Získáno 5. 4 2014, z
Nette Framework 2.1.2 API: http://api.nette.org/2.1.2/source-
Application.UI.Presenter.php.html
[33] Nette Foundation. (2014). Licenční politika. Získáno 6. 5 2014, z Nette Framework:
http://nette.org/cs/license
Seznam literatury 103
[34] Nette Foundation. (2014). MVC aplikace & presentery. Získáno 18. 4 2014, z Nette
Framework: http://doc.nette.org/cs/2.1/presenters
[35] Nette Foundation. (2014). Píšeme komponenty. Získáno 18. 4 2014, z Nette
Framework: http://doc.nette.org/cs/2.1/components
[36] Nette Foundation. (2014). Požadavky Nette Framework. Získáno 29. 3 2014, z Nette
Framework: http://doc.nette.org/cs/2.1/requirements
[37] Nette Foundation. (2014). Routování URL. Získáno 5. 4 2014, z Rychlý a pohodlný
vývoj webových aplikací v PHP | Nette Framework: http://doc.nette.org/cs/2.1/routing
[38] Nette Foundation. (2014). Rozšíření jazyka PHP. Získáno 18. 4 2014, z Nette
Framework: http://doc.nette.org/cs/2.1/php-language-enhancements
[39] Nette Foundation. (2014). Slovníček pojmů. Získáno 5. 4 2014, z Nette Framework:
http://nette.org/cs/glossary#toc-presenter
[40] Phalcon Framework Team. (6. 1 2014). cphalcon/docs/LICENSE.md at master ·
phalcon/cphalcon. Získáno 6. 5 2014, z GitHub:
https://github.com/phalcon/cphalcon/blob/master/docs/LICENSE.md
[41] Phalcon Team and contributors. (3. 4 2014). Class Phalcon\Mvc\Application. Získáno
5. 4 2014, z Phalcon 1.3.0 documentation:
http://docs.phalconphp.com/en/latest/api/Phalcon_Mvc_Application.html
[42] Phalcon Team and contributors. (2014). Cookies Management. Získáno 23. 4 2014, z
Phalcon 1.3.0 documentation:
http://docs.phalconphp.com/en/latest/reference/cookies.html#encryption-decryption-
of-cookies
[43] Phalcon Team and contributors. (2014). Dependency Injection/Service Location.
Získáno 16. 4 2014, z Phalcon 1.3.0 documentation:
http://docs.phalconphp.com/en/latest/reference/di.html#complex-registration
[44] Phalcon Team and contributors. (2014). Improving Performance with Cache. Získáno
25. 4 2014, z Phalcon 1.3.0 documentation:
http://docs.phalconphp.com/en/latest/reference/cache.html
[45] Phalcon Team and contributors. (2014). Installation. Získáno 2. 5 2014, z Phalcon
1.3.0 documentation: http://docs.phalconphp.com/en/latest/reference/install.html
[46] Phalcon Team and contributors. (2014). Internationalization. Získáno 24. 4 2014, z
Phalcon 1.3.0 documentation: http://docs.phalconphp.com/en/latest/reference/intl.html
[47] Phalcon Team and contributors. (2014). Logging. Získáno 28. 4 2014, z Phalcon 1.3.0
documentation: http://docs.phalconphp.com/en/latest/reference/logging.html
[48] Phalcon Team and contributors. (2014). Phalcon Query Language (PHQL). Získáno
11. 5 2014, z Phalcon 1.3.0 documentation: http://phalcon-php-framework-
documentation.readthedocs.org/en/latest/reference/phql.html#creating-queries-using-
the-query-builder
[49] Phalcon Team and contributors. (2014). Routing. Získáno 5. 4 2014, z Phalcon 1.3.0
documentation: http://docs.phalconphp.com/en/latest/reference/routing.html#http-
method-restrictions
Seznam literatury 104
[50] Phalcon Team and contributors. (2014). Universal Class Loader. Získáno 29. 4 2014,
z Phalcon 1.3.0 documentation:
http://docs.phalconphp.com/en/latest/reference/loader.html
[51] Phalcon Team and contributors. (2014). Using Views. Získáno 20. 4 2014, z Phalcon
1.3.0 documentation:
http://docs.phalconphp.com/en/latest/reference/views.html#disabling-the-view
[52] Phalcon Team and contributors. (2014). User Components. Získáno 18. 4 2014, z
Phalcon 1.3.0 documentation: http://docs.phalconphp.com/en/latest/reference/tutorial-
invo.html#user-components
[53] PHP 5 Tutorial. (2014). Získáno 2014, z W3Schools Online Web Tutorials:
http://www.w3schools.com/php/default.asp
[54] PHP Framework Interoperability Group. (16. 10 2013). Autoloading Standard.
Získáno 29. 4 2014, z GitHub: https://github.com/php-fig/fig-
standards/blob/master/accepted/PSR-0.md
[55] PHP: Introduction - Manual. (2014). Získáno 15. 3 2014, z PHP:
http://www.php.net/manual/en/oop5.intro.php
[56] Q-Success. (7. 5 2014). Usage of server-side programming languages for websites.
Získáno 7. 5 2014, z W3Techs - extensive and reliable web technology surveys:
http://w3techs.com/technologies/overview/programming_language/all
[57] Refsnes Data. (2014). HTML Introduction. Získáno 2. 5 2014, z W3Schools Online
Web Tutorials: http://www.w3schools.com/html/html_intro.asp
[58] Refsnes Data. (2014). HTTP Methods: GET vs. POST. Získáno 8. 5 2014, z
W3Schools Online Web Tutorials:
http://www.w3schools.com/tags/ref_httpmethods.asp
[59] Refsnes Data. (2014). Introduction to XML. Získáno 2. 5 2014, z W3Schools Online
Web Tutorials: http://www.w3schools.com/xml/xml_whatis.asp
[60] Rouse, M. (4 2005). FIFO (first-in, first-out). Získáno 4. 5 2014, z The Tech
Dictionary and IT Encyclopedia: http://whatis.techtarget.com/definition/FIFO-first-in-
first-out
[61] Seemann, M. (2012). A Dependency Injection tasting menu. V Dependency Injection
in .NET (str. 4). Manning Publications Co.
[62] Seemann, M. (2012). DI patterns. V Dependency Injection in .NET (stránky 95-132).
Manning Publications Co.
[63] Seemann, M. (2012). Putting Dependency Injection on the map. V Dependency
Injection in .NET (str. 1). Manning Publications Co.
[64] Shafik, D., & Ramsey, B. (2007). Sessions. V Zend PHP 5 Certification Study Guide
2nd Edition (str. 109). Toronto: Marco Tabini & Associates, Inc.
[65] Skvorc, B. (28. 12 2013). Best PHP Frameworks for 2014. Získáno 15. 3 2014, z
SitePoint – Learn HTML, CSS, JavaScript, PHP, Ruby & Responsive Design:
http://www.sitepoint.com/best-php-frameworks-2014/
Seznam literatury 105
[66] Sluiman, J. (12 2012). Using Zend Framework service managers in your application.
Získáno 16. 4 2014, z Jurian Sluiman: https://juriansluiman.nl/article/120/using-zend-
framework-service-managers-in-your-application
[67] SourceMaking. (nedatováno). Facade Design Pattern. Získáno 6. 5 2014, z
SourceMaking: http://sourcemaking.com/design_patterns/facade
[68] Studentův t-test a F-test. (21. 10 2010). Získáno 10. 5 2014, z sofe2 wiki:
http://sofe2.pepiino.cz/wiki/doku.php?id=studentuv_t-test_a_f-test
[69] The Open Source Initiative. (nedatováno). The BSD 3-Clause License. Získáno 28. 4
2014, z Open Source Initiative: http://opensource.org/licenses/BSD-3-Clause
[70] The PHP Group. (2014). PHP: General Information - Manual. Získáno 9. 3 2014, z
PHP: Hypertext Preprocessor: http://cz2.php.net/manual/en/faq.general.php
[71] The PHP Group. (2014). Runtime Configuration. Získáno 6. 5 2014, z PHP: Hypertext
Preprocessor:
http://www.php.net/manual/en/opcache.configuration.php#ini.opcache.enable
[72] The PHP Group. (2014). ZendOpcache. Získáno 6. 5 2014, z PECL:
http://pecl.php.net/package/ZendOpcache
[73] The PHP Group. (nedatováno). Passing the Session ID. Získáno 7. 5 2014, z PHP:
Hypertext Preprocessor: http://www.php.net/manual/en/session.idpassing.php
[74] The PHP Group. (nedatováno). Type Hinting. Získáno 4. 5 2014, z PHP: Hypertext
Preprocessor: http://www.php.net/manual/en/language.oop5.typehinting.php
[75] Thomas, R. (16. 2 2014). Handling 404 and 500 error pages in the Phalcon PHP
Framework. Získáno 28. 4 2014, z Roger E Thomas | Web Application Developer:
http://www.rogerethomas.com/blog/handling-404-and-500-error-pages-in-the-
phalcon-php-framework
[76] Tölg, J. (2012). Framework Nette.
[77] Vanguard Software Corporation. (2013). Compiled vs. Interpreted Languages.
Získáno 9. 3 2014, z Vanguard Software Corporation - Forecasting & Planning:
http://www.vanguardsw.com/dphelp4/dph00296.htm
[78] Weier O'Phinney, M. (12. 3 2014). Zend Framework 2.3.0 Released! - Zend
Framework - Zend Framework. Získáno 29. 3 2014, z Zend Framework:
http://framework.zend.com/blog/zend-framework-2-3-0-released.html
[79] Zend Technologies Ltd. (2014). Advanced usage of helpers. Získáno 19. 4 2014, z
Zend Framework 2 2.3.1 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.view.helpers.advanced-
usage.html
[80] Zend Technologies Ltd. (2014). Available Controllers. Získáno 30. 3 2014, z Zend
Framework 2 2.3.0 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.mvc.controllers.html
[81] Zend Technologies Ltd. (2014). Console routes and routing. Získáno 30. 3 2014, z
Zend Framework 2 2.3.0 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.console.routes.html#zend-
console-routes
Seznam literatury 106
[82] Zend Technologies Ltd. (2014). Controller Plugins. Získáno 30. 3 2014, z Zend
Framework 2 2.3.0 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.mvc.plugins.html#zend-mvc-
controller-plugins-redirect
[83] Zend Technologies Ltd. (2014). Introduction to the MVC Layer. Získáno 18. 4 2014, z
Zend Framework 2 2.3.1 documentation:
http://framework.zend.com/manual/2.3/en/modules/zend.mvc.intro.html
[84] Zend Technologies Ltd. (2014). Learning Dependency Injection. Získáno 16. 4 2014, z
Zend Framework 2 2.3.1 documentation:
http://framework.zend.com/manual/2.3/en/tutorials/quickstart.di.html
[85] Zend Technologies Ltd. (2014). New BSD License. Získáno 6. 5 2014, z Zend
Framework: http://framework.zend.com/license
[86] Zend Technologies Ltd. (2014). Password. Získáno 23. 4 2014, z Zend Framework 2
2.3.1 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.crypt.password.html
[87] Zend Technologies Ltd. (2014). Quick Start. Získáno 20. 4 2014, z Zend Framework 2
2.3.1 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.form.quick-start.html
[88] Zend Technologies Ltd. (2014). Routing. Získáno 30. 3 2014, z Zend Framework 2
2.3.0 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.mvc.routing.html
[89] Zend Technologies Ltd. (2014). Session Container. Získáno 23. 4 2014, z Zend
Framework 2 2.3.1 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.session.container.html
[90] Zend Technologies Ltd. (2014). Session Validators. Získáno 23. 4 2014, z Zend
Framework 2 2.3.1 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.session.validator.html
[91] Zend Technologies Ltd. (2014). The ModuleAutoloader. Získáno 29. 4 2014, z Zend
Framework 2 2.3.1 documentation:
http://framework.zend.com/manual/2.3/en/modules/zend.loader.module-
autoloader.html
[92] Zend Technologies Ltd. (2014). Zend\Cache\Pattern. Získáno 25. 4 2014, z Zend
Framework 2 2.3.1 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.cache.pattern.html
[93] Zend Technologies Ltd. (2014). Zend\Cache\Storage\Adapter. Získáno 25. 4 2014, z
Zend Framework 2 2.3.1 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.cache.storage.adapter.html
[94] Zend Technologies Ltd. (2014). Zend\Cache\Storage\Plugin. Získáno 25. 4 2014, z
Zend Framework 2 2.3.1 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.cache.storage.plugin.html
[95] Zend Technologies Ltd. (2014). Zend\Log. Získáno 26. 4 2014, z Zend Framework 2
2.3.1 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.log.overview.html
Seznam literatury 107
[96] Zend Technologies Ltd. (2014). Zend\Stdlib\Hydrator. Získáno 20. 4 2014, z Zend
Framework 2 2.3.1 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.stdlib.hydrator.html#zend-
stdlib-hydrator
[97] Zend Technologies Ltd. (2014). Zend\View Quick Start. Získáno 19. 4 2014, z Zend
Framework 2 2.3.1 documentation - Zend Framework:
http://framework.zend.com/manual/2.3/en/modules/zend.view.quick-start.html
[98] Žižka, M. (28. 1 2008). Vícekriteriální rozhodování. Získáno 1. 5 2014, z MultiEdu:
http://multiedu.tul.cz/~miroslav.zizka/multiedu/Vicekriterialni_rozhodovani.pdf
Seznam obrázků a tabulek 108
Seznam obrázků a tabulek
Základní text
Seznam obrázků Obrázek 1: ......................................................................................................................... 32 Obrázek 2: ......................................................................................................................... 85 Obrázek 3: ......................................................................................................................... 89 Obrázek 4: ......................................................................................................................... 89 Obrázek 5: ......................................................................................................................... 90
Seznam tabulek Tabulka 1: Běhové prostředí pro porovnání frameworků (Zdroj: autor) ............................. 20 Tabulka 2: Nastavení Zend OPcache rozšíření (Zdroj: autor) ........................................... 21 Tabulka 3: Výchozí předpoklady pro porovnání frameworků (Zdroj: autor) ....................... 23 Tabulka 4: Výsledky rychlostního měření – domovská stránka (Zdroj: autor) ................... 85 Tabulka 5: Výsledky rychlostního měření – seznam knih (Zdroj: autor) ............................ 86 Tabulka 6: Výsledky rychlostního měření – detail knihy (Zdroj: autor) .............................. 86 Tabulka 7: Výsledky výkonnostního srovnání databázových vrstev – získání seznamu všech knih (Zdroj: autor) .................................................................................................... 87 Tabulka 8: Výsledky výkonnostního srovnání databázových vrstev – získání jedné knihy (Zdroj: autor) ............................................................................................................ 88 Tabulka 9: Licenční omezení frameworků (Zdroj: (Zend Technologies Ltd., 2014), (Nette Foundation, 2014), (Phalcon Framework Team, 2014)) .......................................... 92 Tabulka 10: Porovnání dalších faktorů spojených s dokumentací frameworků (Zdroj: autor) ............................................................................................................ 93 Tabulka 11: Absolutní srovnání v rámci komunitních serverů ke dni 28. 4. 2014 (Zdroj: autor) ............................................................................................................ 94 Tabulka 12: Aktuální počet nabídek na pracovních portálech – stav ke dni 3. 5. 2014 (Zdroj: autor) ............................................................................................................ 95 Tabulka 13: Dostupnost rozšíření (Zdroj: autor) ................................................................ 96
Seznam obrázků a tabulek 109
Přílohy
Seznam tabulek Tabulka 14: Identifikace typu stránky pro účely analýzy logu – 1. fáze (Zdroj: autor) ..... 110 Tabulka 15: Identifikace typu stránky pro účely analýzy logu – 2. fáze (Zdroj: autor) ..... 110 Tabulka 16: Výsledky rychlostního měření – domovská stránka (Zdroj: autor) ............... 111 Tabulka 17: Výsledky rychlostního měření – seznam knih (Zdroj: autor) ........................ 111 Tabulka 18: Výsledky rychlostního měření – detail knihy (Zdroj: autor) .......................... 112 Tabulka 19: Výsledky rychlostního měření se zapnutým akcelerátorem – domovská stránka (Zdroj: autor) ....................................................................................................... 113 Tabulka 20: Výsledky rychlostního měření se zapnutým akcelerátorem – seznam knih (Zdroj: autor) .......................................................................................................... 113 Tabulka 21: Výsledky rychlostního měření se zapnutým akcelerátorem – detail knihy (Zdroj: autor) .......................................................................................................... 114 Tabulka 22: Průměrná maximální paměťová náročnost – domovská stránka (Zdroj: autor) .......................................................................................................... 115 Tabulka 23: Průměrná maximální paměťová náročnost – seznam knih (Zdroj: autor) .... 115 Tabulka 24: Průměrná maximální paměťová náročnost – detail knihy (Zdroj: autor) ...... 116 Tabulka 25: Průměrná maximální paměťová náročnost se zapnutým akcelerátorem – domovská stránka (Zdroj: autor) ............................................................ 117 Tabulka 26: Průměrná maximální paměťová náročnost se zapnutým akcelerátorem – seznam knih (Zdroj: autor)..................................................................... 117 Tabulka 27: Průměrná maximální paměťová náročnost se zapnutým akcelerátorem – detail knihy (Zdroj: autor) ....................................................................... 118 Tabulka 28: Identifikace typu dotazu pro porovnání databázových vrstev frameworků pro účely analýzy logu – 1. způsob tvorby dotazu (Zdroj: autor) ...................................... 119 Tabulka 29: Identifikace typu dotazu pro porovnání databázových vrstev frameworků pro účely analýzy logu – 2. způsob tvorby dotazu (Zdroj: autor) ...................................... 119 Tabulka 30: Výsledky rychlostního měření databázových vrstev – získání seznamu všech knih, údaje jsou v milisekundách zaokrouhlených na 5 desetinných míst (Zdroj: autor) .. 119 Tabulka 31: Výsledky rychlostního měření databázových vrstev – získání jedné knihy, údaje jsou v milisekundách zaokrouhlených na 5 desetinných míst (Zdroj: autor) ........... 120 Tabulka 32: Průměrná maximální paměťová náročnost zjištěná při měření výkonnosti databázových vrstev – získání seznamu všech knih, údaje jsou v megabytech zaokrouhlených na 5 desetinných míst (Zdroj: autor) ...................................................... 122 Tabulka 33: Průměrná maximální paměťová náročnost zjištěná při měření výkonnosti databázových vrstev – získání jedné knihy, údaje jsou v megabytech zaokrouhlených na 5 desetinných míst (Zdroj: autor) ................................................................................ 123
Příloha A: Výsledky rychlostního měření 110
Příloha A: Výsledky rychlostního měření
A.1 Celkové zpracování požadavku
Zdrojové kódy aplikací, na kterých bylo prováděno měření, jsou součástí přiloženého ZIP
archivu. Hlavní rozcestník (soubor index.php) obsahuje odkazy do jednotlivých typů aplikací.
Pro účely jednoduché vizualizace naměřených hodnot tabulkovou formou byl vytvořen
skript results.php, který předně zobrazuje souhrnné výsledky měření včetně paměťové nároč-
nosti. Vstupní data jsou zobrazeny níže a je možné se na ně přesunout pomocí hypertexto-
vého odkazu ze souhrnné tabulky.
Jak již bylo zmíněno v kapitole 3.3.14, pro účely logování byla vytvořena pomocná třída
JR\FrameworkComparison\Utils\Logger, která rozlišuje jednotlivé typy stránek na základě de-
finovaných konstant, konkrétní hodnoty jsou uvedeny v tabulkách níže.
Tabulka 14: Identifikace typu stránky pro účely analýzy logu – 1. fáze (Zdroj: autor)
Typ stránky Zend Nette Phalcon
Domovská stránka x nette_homepage_caching phalcon_homepage_caching
Seznam knih x nette_books_caching phalcon_books_caching
Detail knihy x nette_book_caching phalcon_book_caching
Tabulka 15: Identifikace typu stránky pro účely analýzy logu – 2. fáze (Zdroj: autor)
Typ stránky Zend Nette Phalcon
Domovská stránka zend_homepage nette_homepage phalcon_homepage
Seznam knih zend_books nette_books phalcon_books
Detail knihy zend_book nette_book phalcon_book
V tabulce 16, 17 a 18 jsou zaznamenány výsledky měření v jednotlivých fázích bez aktivo-
vaného akcelerátoru rozdělených dle typu stránky. Zdrojem dat je soubor
JR\FrameworkComparison\_results\timelog.csv, který byl následně zpracován pomocí skriptu
results.php, který je rovněž součástí doprovodné aplikace. Tabulky 19, 20 a 21 zobrazují data
ze zdrojového souboru JR\FrameworkComparison\_results\opcache\timelog.csv, který obsahuje
hodnoty naměřené v prostředí se zapnutým akcelerátorem. Veškeré hodnoty jsou uvedeny
v milisekundách se zaokrouhlením na 5 desetinných míst. Průměrné hodnoty, hodnoty me-
diánu a velikost směrodatné odchylky (SO) jsou uvedeny vždy v posledních třech řádcích
tabulky.
Příloha A: Výsledky rychlostního měření 111
Tabulka 16: Výsledky rychlostního měření – domovská stránka (Zdroj: autor)
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
1. x 202,02518 306,41508 109,64394 26,01719 3,78513
2. x 210,00409 288,29789 106,72402 10,16903 3,76701
3. x 196,10596 298,33412 110,25906 11,45887 4,05312
4. x 217,93008 272,83311 113,49702 10,99896 4,13895
5. x 277,70591 278,11503 109,26604 9,70507 4,09293
6. x 258,111 274,03021 121,70696 10,67996 3,75605
7. x 217,91697 279,30999 122,10393 11,3039 3,77607
8. x 204,19097 295,50409 116,79983 12,55393 4,12607
9. x 199,09596 275,32887 113,95502 9,53913 7,71308
10. x 215,77311 270,86806 109,44104 12,09712 3,87096
Průměr x 219,88592 283,90365 113,33969 12,45232 4,30794
Medián x 212,8886 278,71251 111,87804 11,15143 3,96204
SO x 26,85273 12,41409 5,35318 4,86426 1,20702
Tabulka 17: Výsledky rychlostního měření – seznam knih (Zdroj: autor)
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
1. x 217,11302 323,11106 121,65713 27,25005 9,40299
2. x 198,98796 302,43707 121,21797 12,87317 8,78906
3. x 197,16311 308,599 119,08889 14,08219 12,98213
4. x 206,141 311,25593 118,26587 16,29996 9,14097
5. x 206,36916 387,97402 109,10606 15,42091 9,1958
6. x 206,05397 392,90309 116,14394 13,47899 9,30309
7. x 233,96015 280,02596 122,91718 20,64109 8,92401
8. x 203,78494 305,07398 115,80992 18,16988 8,52799
Příloha A: Výsledky rychlostního měření 112
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
9. x 225,87204 267,58099 119,36593 13,85713 9,00507
10. x 216,8889 281,68201 118,67499 14,44292 8,58903
Průměr x 211,23343 316,06431 118,22479 16,65163 9,38601
Medián x 206,25508 306,83649 118,88194 14,93192 9,07302
SO x 11,91252 42,6116 3,92038 4,41988 1,29622
Tabulka 18: Výsledky rychlostního měření – detail knihy (Zdroj: autor)
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
1. x 264,678 271,95692 127,71797 19,48094 10,02789
2. x 202,11101 281,72302 108,45089 12,36916 8,3518
3. x 213,99307 266,74986 108,52313 18,73684 8,19898
4. x 204,83994 275,06399 114,26282 19,21105 7,93195
5. x 220,98899 273,30494 129,01807 15,53988 8,40592
6. x 205,68013 272,73822 121,876 12,35008 7,84707
7. x 196,00987 264,2231 118,36791 11,43384 8,08287
8. x 201,653 274,07098 113,47699 17,0722 9,91607
9. x 221,17901 280,95388 118,02197 15,16199 8,74686
10. x 199,27096 275,44594 122,48898 16,32094 8,71396
Průměr x 213,0404 273,62309 118,22047 15,76769 8,62234
Medián x 205,26004 273,68796 118,19494 15,93041 8,37886
SO x 20,12999 5,41818 7,19631 2,96085 0,77037
Příloha A: Výsledky rychlostního měření 113
Tabulka 19: Výsledky rychlostního měření se zapnutým akcelerátorem – domovská stránka
(Zdroj: autor)
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
1. x 113,2741 169,22998 46,14115 23,53406 5,79619
2. x 65,9678 173,90394 31,64196 20,28179 5,60594
3. x 181,02479 169,56592 36,49402 14,12082 6,3858
4. x 68,17913 204,4692 33,83303 15,72108 5,98407
5. x 90,70897 171,15998 30,21598 12,47001 4,02308
6. x 65,58108 161,5572 36,95011 10,52284 4,91381
7. x 105,84593 198,97699 36,9401 11,56402 4,1039
8. x 63,76696 183,90894 34,49988 9,67884 7,08508
9. x 90,23404 165,75909 37,30416 13,18884 6,03104
10. x 62,86907 159,47199 32,95398 11,80387 4,96101
Průměr x 90,74519 175,80032 35,69744 14,28862 5,48899
Medián x 79,20659 170,36295 35,49695 12,82942 5,70107
SO x 36,73862 15,28356 4,40114 4,43499 0,98182
Tabulka 20: Výsledky rychlostního měření se zapnutým akcelerátorem – seznam knih (Zdroj:
autor)
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
1. x 120,11909 236,56392 46,15498 16,28613 12,95519
2. x 103,92308 243,56985 41,65483 11,33704 12,63714
3. x 68,08591 229,31004 34,04403 9,12595 12,743
4. x 104,05302 200,35505 47,67799 12,04205 11,19995
5. x 68,69888 191,57314 38,48386 10,41293 10,40983
6. x 107,54704 180,06086 36,17311 12,64095 12,44092
7. x 70,41478 206,79808 44,30604 12,29191 13,28111
Příloha A: Výsledky rychlostního měření 114
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
8. x 101,29714 196,522 34,68513 9,11093 12,28118
9. x 73,17305 201,25914 37,03403 11,15394 10,97107
10. x 104,83503 182,84416 52,72603 16,2971 13,65304
Průměr x 92,2147 206,88562 41,294 12,06989 12,25724
Medián x 102,61011 200,80709 40,06934 11,68954 12,53903
SO x 19,73644 22,21896 6,26086 2,52908 1,05847
Tabulka 21: Výsledky rychlostního měření se zapnutým akcelerátorem – detail knihy (Zdroj: au-
tor)
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
1. x 104,35605 174,88289 59,71098 24,67203 11,78122
2. x 67,83199 182,3051 42,61518 18,45813 11,19995
3. x 99,06101 238,95502 41,95714 15,06805 11,41405
4. x 66,63609 405,60412 55,54509 17,94195 11,10005
5. x 104,24304 182,75809 46,88597 17,53688 14,22596
6. x 74,83482 178,68495 41,29601 18,677 9,76396
7. x 100,92402 180,63188 60,33683 15,589 11,76
8. x 72,67594 198,07887 40,01999 17,74406 10,22506
9. x 100,89588 1452,86584 49,68095 22,60303 10,32114
10. x 68,48598 165,70115 66,60295 13,73792 14,70494
Průměr x 85,99448 336,04679 50,46511 18,20281 11,64963
Medián x 86,94792 182,5316 48,28346 17,84301 11,307
SO x 16,99322 398,83537 9,48553 3,31359 1,62999
Tabulky níže shrnují výsledky porovnání průměrné maximální paměťové náročnosti. Rozli-
šena jsou měření s vypnutým a povoleným akcelerátorem. Hodnoty jsou uvedeny v mega-
bytech a jsou zaokrouhlené na 5 desetinných míst.
Příloha A: Výsledky rychlostního měření 115
Tabulka 22: Průměrná maximální paměťová náročnost – domovská stránka (Zdroj: autor)
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
1. x 3,79124 4,64431 2,9734 0,33894 0,3242
2. x 3,79124 4,64431 2,9734 0,33916 0,3242
3. x 3,79124 4,64431 2,9734 0,33916 0,3242
4. x 3,79124 4,58135 2,9734 0,33916 0,3242
5. x 3,79124 4,58135 2,9734 0,33916 0,3242
6. x 3,79124 4,58135 2,9734 0,33916 0,3242
7. x 3,79124 4,58135 2,9734 0,33916 0,3242
8. x 3,79124 4,58135 2,9734 0,33916 0,3242
9. x 3,79124 4,58135 2,9734 0,33916 0,3242
10. x 3,79124 4,58135 2,9734 0,33916 0,3242
Průměr x 3,79124 4,60024 2,9734 0,33914 0,3242
Medián x 3,79124 4,58135 2,9734 0,33916 0,3242
SO x 0 0,03041 0 0,00007 0
Jelikož během měření bylo sledováno i množství maximální alokované paměti, jsou tyto
údaje zaznamenány v tabulkách uvedených níže. Veškeré hodnoty jsou uváděny v megaby-
tech se zaokrouhlením na 5 desetinných míst.
Tabulka 23: Průměrná maximální paměťová náročnost – seznam knih (Zdroj: autor)
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
1. x 3,87991 4,71152 3,05567 0,38714 0,35107
2. x 3,88052 4,71152 3,05564 0,38735 0,35128
3. x 3,88052 4,71152 3,05564 0,38735 0,35128
4. x 3,88052 4,64574 3,05564 0,38735 0,35128
5. x 3,88052 4,64574 3,05564 0,38735 0,35128
6. x 3,88052 4,64574 3,05564 0,38735 0,35128
Příloha A: Výsledky rychlostního měření 116
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
7. x 3,88052 4,64574 3,05564 0,38735 0,35128
8. x 3,88052 4,64574 3,05564 0,38735 0,35128
9. x 3,88052 4,64574 3,05564 0,38735 0,35128
10. x 3,88052 4,64574 3,05564 0,38735 0,35128
Průměr x 3,88046 4,66547 3,05564 0,38733 0,35126
Medián x 3,88052 4,64574 3,05564 0,38735 0,35128
SO x 0,00019 0,03178 0,00001 0,00007 0,00007
Tabulka 24: Průměrná maximální paměťová náročnost – detail knihy (Zdroj: autor)
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
1. x 3,87669 4,60738 3,00503 0,37941 0,35103
2. x 3,87752 4,60776 3,00503 0,37941 0,35127
3. x 3,87752 4,60776 3,00503 0,37941 0,35127
4. x 3,87752 4,60776 3,00503 0,37941 0,35127
5. x 3,87752 4,60776 3,00503 0,37941 0,35127
6. x 3,87752 4,60776 3,00503 0,37941 0,35127
7. x 3,87752 4,60776 3,00503 0,37941 0,35127
8. x 3,87752 4,60776 3,00503 0,37941 0,35127
9. x 3,87752 4,60776 3,00503 0,37941 0,35127
10. x 3,87752 4,60776 3,00503 0,37941 0,35127
Průměr x 3,87743 4,60772 3,00503 0,37941 0,35125
Medián x 3,87752 4,60776 3,00503 0,37941 0,35127
SO x 0,00026 0,00012 0 0 0,00008
Příloha A: Výsledky rychlostního měření 117
Tabulka 25: Průměrná maximální paměťová náročnost se zapnutým akcelerátorem – domovská
stránka (Zdroj: autor)
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
1. x 1,46624 1,58229 0,94479 0,2051 0,19934
2. x 1,46587 1,58211 0,94052 0,21609 0,19661
3. x 1,46624 1,58211 0,94052 0,21609 0,19661
4. x 1,46587 1,58211 0,94052 0,21609 0,19661
5. x 1,46624 1,58211 0,94052 0,21609 0,19661
6. x 1,46587 1,58211 0,94052 0,21609 0,19661
7. x 1,46624 1,58211 0,94052 0,21609 0,19661
8. x 1,46587 1,58211 0,94052 0,21609 0,19661
9. x 1,46624 1,58211 0,94052 0,21609 0,19661
10. x 1,46587 1,58211 0,94052 0,21609 0,19661
Průměr x 1,46605 1,58213 0,94095 0,215 0,19688
Medián x 1,46605 1,58211 0,94052 0,21609 0,19661
SO x 0,0002 0,00006 0,00135 0,00348 0,00086
Tabulka 26: Průměrná maximální paměťová náročnost se zapnutým akcelerátorem – seznam
knih (Zdroj: autor)
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
1. x 1,49998 1,68223 1,00656 0,25151 0,21249
2. x 1,4995 1,68205 1,00536 0,25073 0,21002
3. x 1,49924 1,68205 1,00536 0,25073 0,21002
4. x 1,4995 1,64265 1,00536 0,25073 0,21002
5. x 1,49924 1,64265 1,00536 0,25073 0,21002
6. x 1,4995 1,64265 1,00536 0,25073 0,21002
7. x 1,49924 1,64265 1,00536 0,25073 0,21002
Příloha A: Výsledky rychlostního měření 118
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
8. x 1,4995 1,64265 1,00536 0,25073 0,21002
9. x 1,49924 1,64265 1,00536 0,25073 0,21002
10. x 1,4995 1,64265 1,00536 0,25073 0,21002
Průměr x 1,49945 1,65449 1,00548 0,25081 0,21027
Medián x 1,4995 1,64265 1,00536 0,25073 0,21002
SO x 0,00023 0,01906 0,00038 0,00025 0,00078
Tabulka 27: Průměrná maximální paměťová náročnost se zapnutým akcelerátorem – detail
knihy (Zdroj: autor)
Měření Zend Nette Phalcon
1. fáze 2. fáze 1. fáze 2. fáze 1. fáze 2. fáze
1. x 1,49373 1,60226 0,9582 0,2421 0,2106
2. x 1,49305 1,60247 0,95501 0,24083 0,20814
3. x 1,49329 1,60247 0,95501 0,24083 0,20814
4. x 1,49305 1,60247 0,95501 0,24083 0,20814
5. x 1,49329 1,60247 0,95501 0,24083 0,20814
6. x 1,49305 1,60247 0,95501 0,24083 0,20814
7. x 1,49329 1,60247 0,95501 0,24083 0,20814
8. x 1,49305 1,60247 0,95501 0,24083 0,20814
9. x 1,49329 1,60247 0,95501 0,24083 0,20814
10. x 1,49305 1,60247 0,95501 0,24083 0,20814
Průměr x 1,49321 1,60245 0,95533 0,24096 0,20838
Medián x 1,49317 1,60247 0,95501 0,24083 0,20814
SO x 0,00022 0,00007 0,00101 0,0004 0,00078
Příloha A: Výsledky rychlostního měření 119
A.2 Výkonnost databázové vrstvy
Princip logování je stejný jako u měření celkové rychlosti zpracování požadavku, liší se
pouze identifikátory daných typů. Rozlišeny jsou oba dva způsoby konstrukce dotazů.
Pro každé měření (označeného číselným pořadím) jsou uvedeny hodnoty ve dvou řádcích.
V prvním z nich leží hodnoty naměřené bez aktivovaného akcelerátoru, v druhém jsou nao-
pak hodnoty naměřené se zapnutým akcelerátorem.
Tabulka 28: Identifikace typu dotazu pro porovnání databázových vrstev frameworků pro účely
analýzy logu – 1. způsob tvorby dotazu (Zdroj: autor)
Zend Nette Phalcon
Získání seznamu
všech knih
zend_db_books nette_db_books phalcon_db_books
Získání jedné knihy zend_db_book nette_db_book phalcon_db_book
Tabulka 29: Identifikace typu dotazu pro porovnání databázových vrstev frameworků pro účely
analýzy logu – 2. způsob tvorby dotazu (Zdroj: autor)
Zend Nette Phalcon
Získání seznamu
všech knih
zend_db_oop_books nette_db_oop_books x
Získání jedné knihy zend_db_oop_book nette_db_oop_book x
Následující sada tabulek shrnuje všechny naměřené hodnoty.
Tabulka 30: Výsledky rychlostního měření databázových vrstev – získání seznamu všech knih,
údaje jsou v milisekundách zaokrouhlených na 5 desetinných míst (Zdroj: autor)
Měření Zend Nette Phalcon
1. způsob 2. způsob 1. způsob 2. způsob 1. způsob 2. způsob
1. 3,59201 24,30606 0,53716 12,85505 0,40603 29,76203
3,25394 7,27081 0,45109 3,92389 0,48614 28,09715
2. 3,721 12,86197 0,53883 12,41493 0,57507 26,016
2,01511 8,45098 0,86498 4,33803 0,42582 23,43392
3. 2,98381 14,87494 0,4859 11,338 0,45395 25,39611
1,86801 5,58686 0,494 2,69294 0,40603 23,51403
4. 2,94781 13,05914 0,48494 12,66479 0,916 18,21303
Příloha A: Výsledky rychlostního měření 120
Měření Zend Nette Phalcon
1. způsob 2. způsob 1. způsob 2. způsob 1. způsob 2. způsob
1,92499 7,31492 0,40197 3,33095 0,48089 20,83015
5. 3,03292 14,72116 0,44394 12,90798 0,45419 22,93897
1,98007 5,20992 0,60892 2,75493 0,59199 24,98698
6. 2,94089 14,3981 0,48399 12,19082 0,38218 22,4402
1,87802 5,07689 0,65899 3,98684 0,453 27,38714
7. 2,882 13,07511 0,4189 13,00812 0,46301 22,52293
2,65098 6,984 0,46301 2,11501 0,44894 23,84281
8. 3,6931 14,07385 0,48614 12,0399 0,45896 22,25995
2,07305 5,18489 0,47493 3,38697 0,44203 24,56808
9. 3,06392 13,70001 0,40197 12,58683 0,60201 23,45085
1,89805 5,23686 0,41914 2,46692 0,40579 23,2389
10. 3,12781 17,82489 0,422 13,81683 0,40793 25,97213
2,27499 8,46505 0,41199 3,75295 0,50688 24,25408
Průměr 3,19853 15,28952 0,47038 12,58233 0,51193 23,89722
2,18172 6,47812 0,5249 3,27494 0,46475 24,41533
Medián 3,04842 14,23597 0,48447 12,62581 0,45657 23,19491
1,99759 6,28543 0,46897 3,35896 0,45097 24,04845
SO 0,33308 3,47677 0,04761 0,65967 0,15851 3,08323
0,44669 1,37453 0,14624 0,7386 0,05581 2,08445
Tabulka 31: Výsledky rychlostního měření databázových vrstev – získání jedné knihy, údaje jsou
v milisekundách zaokrouhlených na 5 desetinných míst (Zdroj: autor)
Měření Zend Nette Phalcon
1. způsob 2. způsob 1. způsob 2. způsob 1. způsob 2. způsob
1. 3,443 16,44707 0,458 10,16903 0,44298 28,04804
2,11692 6,75392 0,50402 2,91705 0,47398 24,32704
Příloha A: Výsledky rychlostního měření 121
Měření Zend Nette Phalcon
1. způsob 2. způsob 1. způsob 2. způsob 1. způsob 2. způsob
2. 3,49998 15,31911 0,52619 11,3771 0,54193 22,81499
1,88112 7,72595 0,44799 2,21491 0,422 25,6269
3. 3,17907 14,75406 0,63896 14,21809 0,52118 25,04611
2,06494 6,85 0,56791 2,46096 0,40483 22,54081
4. 2,97499 13,7589 0,48518 11,05499 0,46802 24,38617
1,76311 6,12497 0,61607 3,53312 0,41103 23,97895
5. 3,03698 15,53011 0,48399 12,17508 0,48304 19,81187
1,81508 7,52902 0,41199 2,97213 0,79703 24,88589
6. 3,30019 16,02602 0,5939 12,42709 0,46492 23,99898
2,02394 6,43206 0,44394 2,02298 0,44489 26,20912
7. 3,11995 14,32109 0,71001 10,39219 0,43797 22,10903
1,90401 8,89993 0,47708 3,03006 0,41699 20,49804
8. 3,31402 15,46097 0,458 10,90312 0,42892 19,36197
1,88088 7,02882 0,48995 3,65019 0,79203 23,35906
9. 3,64304 14,01901 0,86212 13,41081 0,54193 23,83995
2,06494 7,08413 0,42319 3,86286 0,67806 24,40906
10. 3,06678 15,08689 0,60511 11,70301 0,43702 23,6299
2,12002 7,95507 0,52595 2,29096 0,43392 24,94502
Průměr 3,2578 15,07232 0,58215 11,78305 0,47679 23,3047
1,9635 7,23839 0,49081 2,89552 0,52748 24,07799
Medián 3,23963 15,203 0,56005 11,54006 0,46647 23,73493
1,96397 7,05647 0,48351 2,94459 0,43941 24,36805
SO 0,22029 0,86419 0,12979 1,29797 0,04376 2,51639
0,12979 0,81238 0,06502 0,64249 0,16183 1,64055
Příloha A: Výsledky rychlostního měření 122
Tabulka 32: Průměrná maximální paměťová náročnost zjištěná při měření výkonnosti
databázových vrstev – získání seznamu všech knih, údaje jsou v megabytech zao-
krouhlených na 5 desetinných míst (Zdroj: autor)
Měření Zend Nette Phalcon
1. způsob 2. způsob 1. způsob 2. způsob 1. způsob 2. způsob
1. 4,02785 4,37864 2,75584 3,03114 0.39423 0,39423
1,48797 1,58929 0,85804 0,90162 0,2171 0,25397
2. 4,02779 4,37856 2,75584 3,03117 0,35792 0,39405
1,48799 1,58932 0,858 0,89898 0,21712 0,25185
3. 4,02861 4,37934 2,75617 3,03157 0,35811 0,39425
1,48853 1,58959 0,85844 0,89936 0,21735 0,25217
4. 4,02861 4,37934 2,75617 3,03157 0,35811 0,39425
1,48853 1,59016 0,85835 0,89935 0,21735 0,25217
5. 4,02861 4,37934 2,75617 3,03157 0,35811 0,39425
1,48883 1,58959 0,85835 0,89936 0,21735 0,25217
6. 4,02861 4,37934 2,75617 3,03157 0,35811 0,39425
1,48853 1,58959 0,85844 0,89935 0,21735 0,25217
7. 4,02861 4,37934 2,75617 3,03157 0,35811 0,39425
1,48853 1,59016 0,85835 0,89935 0,21735 0,25217
8. 4,02861 4,37934 2,75617 3,03157 0,35811 0,39425
1,48853 1,58959 0,85835 0,89936 0,21735 0,25217
9. 4,02861 4,37934 2,75617 3,03157 0,35811 0,39425
1,48883 1,58959 0,85844 0,89935 0,21735 0,25217
10. 4,02861 4,37934 2,75617 3,03157 0,35811 0,39425
1,48853 1,59016 0,85844 0,89936 0,21735 0,25398
Průměr 4,02845 4,37919 2,75611 3,03149 0,35807 0,39423
1,48848 1,58971 0,85832 0,89954 0,2173 0,2525
Medián 4,02861 4,37934 2,75617 3,03157 0,35811 0,39425
Příloha A: Výsledky rychlostního měření 123
Měření Zend Nette Phalcon
1. způsob 2. způsob 1. způsob 2. způsob 1. způsob 2. způsob
1,48853 1,58959 0,85835 0,89935 0,21735 0,25217
SO 0,00033 0,00031 0,00014 0,00018 0,00009 0,00006
0,00029 0,00034 0,00016 0,00074 0,0001 0,00079
Tabulka 33: Průměrná maximální paměťová náročnost zjištěná při měření výkonnosti
databázových vrstev – získání jedné knihy, údaje jsou v megabytech zaokrouhle-
ných na 5 desetinných míst (Zdroj: autor)
Měření Zend Nette Phalcon
1. způsob 2. způsob 1. způsob 2. způsob 1. způsob 2. způsob
1. 4,02923 4,40786 2,74632 3,03209 0,35815 0,3982
1,48914 1,60245 0,84751 0,89633 0,21403 0,25514
2. 4,03003 4,40874 2,74663 3,03224 0,35837 0,39841
1,48968 1,60387 0,8477 0,89672 0,21426 0,25537
3. 4,03003 4,40874 2,74663 3,03224 0,35837 0,39841
1,48997 1,60329 0,84779 0,89672 0,21426 0,25537
4. 4,03003 4,40874 2,74663 3,03224 0,35837 0,39841
1,48968 1,60329 0,8477 0,89672 0,21426 0,25537
5. 4,03003 4,40874 2,74663 3,03224 0,35837 0,39841
1,48968 1,60387 0,8477 0,89672 0,21426 0,25537
6. 4,03003 4,40874 2,74663 3,03224 0,35837 0,39841
1,48997 1,60329 0,84779 0,89672 0,21426 0,25537
7. 4,03003 4,40874 2,74663 3,03224 0,35837 0,39841
1,48968 1,60387 0,8477 0,89672 0,21426 0,25537
8. 4,03003 4,40874 2,74663 3,03224 0,35837 0,39841
1,48968 1,60329 0,8477 0,89672 0,21426 0,25537
9. 4,03003 4,40874 2,74663 3,03224 0,35837 0,39841
1,48997 1,60387 0,84779 0,89672 0,21426 0,25537
Příloha A: Výsledky rychlostního měření 124
Měření Zend Nette Phalcon
1. způsob 2. způsob 1. způsob 2. způsob 1. způsob 2. způsob
10. 4,03003 4,40874 2,74663 3,03224 0,35837 0,39841
1,48997 1,60329 0,8477 0,89672 0,21426 0,25537
Průměr 4,02995 4,40865 2,7466 3,03223 0,35835 0,39839
1,48974 1,60344 0,84771 0,89668 0,21423 0,25535
Medián 4,03003 4,40874 2,74663 3,03224 0,35837 0,39841
1,48968 1,60329 0,8477 0,89672 0,21426 0,25537
SO 0,00025 0,00028 0,0001 0,00005 0,00007 0,00007
0,00026 0,00045 0,00008 0,00012 0,00007 0,00007