Úvod
Na první pohled se může zdát, že frameworků pro PHP je velké množství. Pokud se však na výběr zaměříme detailněji, zjistíme, že ne každý vyhovuje našim představám. Některé frameworky mají nepřeberné množství knihoven, které obstarávají téměř vše, na co si vzpomenete. To je ovšem vykoupeno jejich vyššími hardwarovými nároky a nižší rychlostí. Jiné mají knihoven méně, ale dají se, díky své modulárnosti, lehce rozšířit o nové funkce. Velká pozornost se musí věnovat dokumentaci jednotlivých frameworků. Pokud je dokumentace na špatné úrovni, práce s frameworkem trvá mnohem déle, protože je třeba dlouze vyhledávat parametry funkcí či řešení jiných úskalí.
Nikde na internetu není zpracována studie, která by testovala frameworky dle všech výše uvedených aspektů. Dostupné testy jednotlivých frameworků ukazují pouze rychlosti a paměťové nároky při vypsání fráze „Hello World!“. Takový test se nepodobá reálně používaným aplikacím, protože při něm není využita komunikace s databází. Z tohoto důvodu byly udělány testy nejrozšířenějších PHP frameworků, které se více blíží reálné aplikaci. Cílem testů je vybrat framework, který skutečně ulehčí práci a zároveň jsme pomocí něj schopni vytvořit i robustnější aplikaci v kratším čase než při použití čistého PHP.
Na začátek je ještě nutno zdůraznit, že absolutní hodnoty naměřených výsledků vůči reálnému provozu nejsou až tak důležité. A to z důvodu, že měření neprobíhalo na serverech k tomu určených, ale na noteboocích a rovněž rozdíly mezi naměřenými hodnotami jsou velké. V článku však jde hlavně o relativní srovnání výsledků testů mezi jednotlivými frameworky.
Průběh testování
Pro testování byly založeny dvě MySQL tabulky a to tabulka „members“ a „users“. V tabulce „members“ jsou uvedeni imaginární členové sdružení. Tito členové mohou mít pod sebou další uživatele, kteří jsou uloženi v tabulce „users“, kde sloupec „id_member“ poukazuje na člena, ke kterému daný uživatel patří.
Obr. 1. Schéma testovacích tabulekTestování probíhalo na dvou počítačích. Na prvním z nich běžel testovací program Apache JMeter a na druhém počítači byly umístěny samotné testované stránky. Rozdělení na dva počítače bylo nutné z důvodu oddělení stránek a testovacího programu, který měl vyšší nároky, čímž výrazně ovlivňoval výsledky testů. U použitých počítačů se v obou případech jednalo o notebook Fujitsu Siemens AMILO Pro V2040 v konfiguraci:
- Procesor: 1.6 GHz Pentium (M725) (Intel Pentium M Dothan (2 MB cache))
- Paměť: 512 MB (PC4300 SO-DIMM 200pin (DDR2–533))
- HDD: 60 GB, 5400 otáček
Počítače byly propojeny místní sítí 100 Mbit/s. Program JMeter běžel pod operačním systémem Windows XP Home edition. Testované stránky běžely pod operačním systémem Linux Kubuntu 7.10 s konfigurací:
- PHP 5.2.3–1
- MySQL 5.0.45
- eAccelerator v0.9.5.2
Na každém frameworku byly provedeny testy jak s vypnutým, tak i zapnutým eAcceleratorem. Všechny testy byly prováděny třikrát. Pro následné srovnání byly použity průměrné hodnoty z těchto tří testů.
Jednotlivé kroky testu
Při testování se nejprve vypsala tabulka se všemi členy. U každého člena byly vypsány základní informace, jako je jméno, adresa a typ členství. Výpis členů můžeme vidět na obrázku Obr. 2, kde je rovněž vidět odkaz na uživatele daného člena, pomocí kterého se dostáváme do dalšího kroku.
Obr. 2. První krok testu – členové sdruženíV dalším kroku byl proveden výběr uživatelů patřících k vybranému členovi. Ke každému uživateli jsou opět vypsány základní informace. V tomto kroku bylo rovněž zaznamenávána paměťová náročnost frameworků (pomocí PHP funkce memory_get_usage). Kompletní tabulku z kroku dva můžete vidět na níže uvedeném obrázku.
Obr. 3. Druhý krok testu – výpis uživatelů vybraného členaV třetím kroku se editují data uživatele. Tím otestujeme rychlost i při UPDATE dotazu. Formulář s údaji je zpracován kontrolerem, který při úspěšné editaci přesměruje zpět na výpis uživatelů a vypíše informační text.
V každém kroku je navíc prováděn další MySQL dotaz, který vybírá jméno člena, jehož uživatele aktuálně zobrazujeme. Takto získané jméno je použito ve zpětných odkazech.
Obr. 4. Třetí krok testu – editace uživateleDále jsme se pokusili přibližně změřit čas, který jednotlivé frameworky potřebují k získání dat z databáze. To jsme realizovali vložením měřící funkce těsně před funkci obstarávající práci s databází a za ní. Rozdílem těchto dvou časů jsme získali hrubý čas potřebný pro komunikaci se samotnou databází. Tento test byl prováděn samostatně po dokončení všech testů, tak, aby neovlivnil celkové výsledky.
Realizace v programu Apache JMeter
Testovací plán v JMeteru se skládal z výše uvedených kroků, včetně odeslání POST dotazu pro změnu údajů uživatele. Testovací schéma je zobrazeno na obrázku Obr. 5. Ramp-up perioda, což je doba, za kterou dojde k vytvoření zadaného počtu uživatelů, byla nastavena na 10 vteřin. Počet uživatelů, kteří přistupují paralelně k aplikaci, byl nastaven na 10 (což při Ramp-up periodě 10 znamená, že se každou vteřinu připojil nový uživatel). Všichni uživatelé vykonají zadané kroky třikrát, přičemž v update dotazu mění každý z nich jméno uživatele na tvar „číslo opakování-číslo threadu“ (tedy například „2–10“). Z toho vyplývá, že pro testovaný framework dostaneme 30 zobrazení jednotlivých kroků.
Při testování byly zaznamenávány především délky trvání jednotlivých akcí, které jsou vyneseny do grafů ukazujících rychlost testovaného frameworku.
Obr. 5. Testovací schémaPři jednom testu tedy dostáváme 120 vzorků (30× zobrazení členů, 30× zobrazení uživatelů, 30× editační formulář a 30× samotný update dotaz), které ukazují rychlost daného frameworku.
Nyní bude následovat přehled a výsledky jednotlivých frameworků a na konci jejich vzájemné porovnání. Ještě předtím, než budete pokračovat, musím zdůraznit, že nejsme odborníci na testované frameworky. Každý z nich jsme poznávali prakticky od začátku a aplikace jsme tvořili pomocí dostupné dokumentace a tutoriálů. U všech testovaných frameworků nebylo zapínáno cachování a byla vesměs použita základní konfigurace.
Akelos
Tento MVC framework je k dispozici na stránce http://www.akelos.org/, kde jej naleznete ve verzi 0.8. Akelos je určen jak pro PHP4 tak PHP5. Přebírá některé funkce ze známého frameworku Ruby on Rais určeného pro programovací jazyk Ruby.
- Pro přístup k databázi používá Active Record, což je druh objektově-relačního mapování. Podporuje databáze MySQL, PostgreSQL (7.4+) a SQLite.
- Obsahuje několik základních pluginů jako je kalendář, asistent pro vytváření základního administračního rozhraní, či dynamic_finder, který umožňuje magické vyhledávání v Active Record modelech ($Model→find_by_user_and_name(‚John‘, ‚Smith‘)). Lze jej dále rozšiřovat přidáváním nových pluginů.
- Pro pohledy používá HTML v kombinaci se Syntags, což je použití zástupných textů pro určité PHP příkazy, čímž se šablony zpřehledňují. Šablony jsou rozděleny dle názvů kontrolerů do adresářů, kde název souboru odpovídá názvu metody a mají příponu .tlp (například uzivatele/edit.tlp).
- Chybí pokročilejší validace. Obsahuje pouze validační funkci pro požadované položky, pokud však chceme zajistit minimální velikost nějaké položky jsme nuceni použít rozhodovací příkaz IF.
- V každém kontroleru definujeme modely, se kterými je svázán. Poté můžeme využívat jejich funkcí.
- Obsahuje standardní helpery pro práci s formuláři, url, datem a časem, navíc má také JavaScript helpery.
- Jednoduchá konfigurace za pomoci grafického rozhraní.
- Možnost vygenerování všech modelů a kontrolerů. Stačí nadefinovat databázi a spustit generátor, který vygeneruje všechny potřebné soubory včetně pohledů.
Dokumentace a uživatelská podpora
Na stránkách se nalézá pouze API dokumentace, ale nikde nenalezneme dokumentaci, která by popisovala jednotlivé helpery a ostatní funkce. Jediným místem kde je k nalezení popis funkcí frameworku je uživatelská wiki, kterou vytváří komunita okolo Akelosu. Nicméně i tato wiki je dosti nepřehledná.
Na stránkách nalezneme video tutoriál s názvem „Vytvoření blogu ve dvaceti minutách“. Tento je dobře zpracován a ukazuje i samotnou instalaci Akelosu.
Komunita zde má své fórum a emailovou konferenci, ale postrádám zde oficiální IRC kanál (existuje několik IRC kanálů, nejsou ovšem uvedeny na oficiálních stránkách).
Ukázka zdrojových kódů
Ukázka práce s pohledem – použití Syntags:
1 {loop users} 2 <tr {?user_odd_position}class="odd"{end}> 3 {loop content_columns} 4 <td class="field"><?php echo $user->get($content_column) ?></td> 5 {end} 6 <td class="operation"><?php echo $uziv_helper->link_to_show($user)?></td> 7 </tr> 8 {end}
Ukázka kontroleru – funkce obstarávající vykreslení editačního formuláře a následné uložení dat po odeslání formuláře:
9 function edit() 10 { 11 if(!empty($this->params['id'])){ 12 if(empty($this->user->id) || $this->user->id != $this->params['id']){ 13 $this->user =& $this-> user->find($this->params['id']); 14 } 15 }else{ 16 $this->redirectToAction('listing'); 17 } 18 19 if(!empty($this->params[user])){ 20 $this->uzivatele->setAttributes($this->params[user]); 21 if($this->Request->isPost() && $this-> user->save()){ 22 $this->flash['notice'] = $this->t('User was successfully updated.'); 23 $this->redirectTo(array('action' => 'show', 'id' => $this->user->getId())); 24 } 25 } 26 }
Model je velice jednoduchý, zde je celý jeho obsah:
1 <?php 2 class Users extends ActiveRecord 3 { 4 var $belongs_to = 'member'; 5 } 6 ?>
Výsledky testů bez použití eAcceleratoru
Akce | Vzorky | Průměr [ms] | Median [ms] | Min [ms] | Max [ms] | Sm. Odch. [ms] | Modus [ms] |
---|---|---|---|---|---|---|---|
První test | |||||||
Zobrazení členů | 30 | 995 | 875 | 187 | 2219 | 644,75 | 187 |
Zobrazení uživatelů | 30 | 992 | 734 | 172 | 2547 | 733,93 | 172 |
Editace uživatele | 30 | 1637 | 906 | 156 | 17703 | 3089,56 | 1781 |
Upravení dat | 30 | 2006 | 1937 | 328 | 4860 | 1143,82 | 344 |
Celkem | 120 | 1408 | 1078 | 156 | 17703 | ||
Druhý test | |||||||
Zobrazení členů | 30 | 1037 | 782 | 312 | 2891 | 694,65 | 484 |
Zobrazení uživatelů | 30 | 1038 | 922 | 187 | 2390 | 661,29 | 625 |
Editace uživatele | 30 | 1159 | 891 | 250 | 2656 | 752,83 | 453 |
Upravení dat | 30 | 2056 | 2078 | 610 | 4766 | 991,33 | N/A |
Celkem | 120 | 1323 | 1109 | 187 | 4766 | ||
Třetí test | |||||||
Zobrazení členů | 30 | 1262 | 1219 | 203 | 3093 | 784,29 | 1031 |
Zobrazení uživatelů | 30 | 1137 | 859 | 156 | 3500 | 816,19 | N/A |
Editace uživatele | 30 | 953 | 750 | 172 | 2875 | 672,41 | 484 |
Upravení dat | 30 | 1683 | 1578 | 656 | 3531 | 741,16 | 1015 |
Celkem | 120 | 1259 | 1125 | 156 | 3531 |
Obr. 6. Průměrné časy zpracovávaných akcí v Akelosu bez eAcceleratoru
Paměťové nároky: 6538,49 kB
Akce | Průměrný čas [ms] |
---|---|
Výpis všech členů | 17,43 |
Jméno člena | 32,51 |
Všichni uživatelé člena | 6,57 |
Načtení jednoho uživatele | 20,15 |
Update dotaz | 86,33 |
Celkem | 27,78 |
Výsledky testů s použitím eAcceleratoru
Akce | Vzorky | Průměr [ms] | Median [ms] | Min [ms] | Max [ms] | Sm. Odch. [ms] | Modus [ms] |
---|---|---|---|---|---|---|---|
První test | |||||||
Zobrazení členů | 30 | 178 | 78 | 46 | 1937 | 363,54 | 78 |
Zobrazení uživatelů | 30 | 77 | 62 | 31 | 203 | 44,97 | 47 |
Editace uživatele | 30 | 75 | 63 | 46 | 172 | 36,73 | 47 |
Upravení dat | 30 | 158 | 110 | 62 | 391 | 93,94 | 94 |
Celkem | 120 | 122 | 78 | 31 | 1937 | ||
Druhý test | |||||||
Zobrazení členů | 30 | 71 | 63 | 46 | 110 | 20,22 | 62 |
Zobrazení uživatelů | 30 | 55 | 47 | 31 | 110 | 17,56 | 47 |
Editace uživatele | 30 | 48 | 47 | 31 | 79 | 14,75 | 47 |
Upravení dat | 30 | 189 | 172 | 93 | 422 | 87,53 | 109 |
Celkem | 120 | 91 | 63 | 31 | 422 | ||
Třetí test | |||||||
Zobrazení členů | 30 | 78 | 78 | 47 | 140 | 23,08 | 78 |
Zobrazení uživatelů | 30 | 51 | 47 | 31 | 109 | 15,98 | 47 |
Editace uživatele | 30 | 52 | 47 | 31 | 109 | 17,31 | 47 |
Upravení dat | 30 | 183 | 157 | 93 | 453 | 80,75 | 125 |
Celkem | 120 | 91 | 63 | 31 | 453 |
Obr. 7. Průměrné časy zpracovávaných akcí v Akelosu s eAcceleratorem
Paměťové nároky: 6538,49 kB
Framework: 1228,24 kB eAccelerator: 4536,32 kB Celkem: 5764,56 kB
Zhodnocení
Na výše uvedených grafech můžeme sledovat, že nejvíce času zabírá upravení dat uživatele. Bez použití eAcceleratoru jsou časy nad jednu vteřinu, což je neúnosné. Framework má své přednosti v podobě generátoru aplikací avšak jeho hlavním nedostatkem je dokumentace, která je na velmi špatné úrovni. Z tohoto důvodu tento framework nedoporučuji pro další práci.
Příklad webu postaveného na tomto frameworku: http://www.thechemicalbrothers.com
CakePHP
Framework naleznete na stránce http://www.cakephp.org/, kde je ve verzi 1.1.19.6305 . Rovněž zde naleznete novější verzi 1.2.0.6311, která je ovšem ve stavu beta verze. Cake je určen pro PHP 4 i PHP 5. Patří mezi jeden z nejvíce rozšířených PHP frameworků, z toho důvodu je na internetu k dispozici i mnoho českých návodů.
Základní vlastnosti
- Používá ORM knihovnu. Možnost připojení na databáze MySQL (4+), PostgreSQL, ADOdb a od verze 1.2 také na Firebird DB2, MSSQL, Oracle, SQLite, ODBC.
- Obsahuje komponenty pro práci s e-maily, autentifikaci a mnoho dalších. Je snadné napsat pro něj nové pluginy. Mnoho pluginů je ke stažení na internetu, například také plugin pro administraci phpGACLu.
- Pohledy jsou rozděleny na několik kategorií – celkový design, samostatná stránka a elementy, které lze chápat jako části stránek. Vše je přehledně rozděleno a není tak problém změnit vzhled celé stránky v několika minutách. Soubory pohledů mají koncovku ctp a obsahují kombinaci HTML a PHP.
- Velmi dobře zpracovaná validace, která se provádí v modelu. Možno určit pravidla, co se může či nesmí vyskytovat, určit omezení délky a v případě nedodržení pravidel definovat chybovou hlášku.
- V modelu můžeme definovat callbacky, díky kterým rozšíříme možnosti práce s daty. Callbacky jsou například BeforeSave, AfterDelete a další.
- Kromě standardních helperů zde můžeme nalézt také helpery pro ajax či RSS.
- Nastavení se provádí změnou konfiguračních souborů. V php.ini je nutno definovat include_path na složku se systémem, ve které je umístěna systémová část CakePHP.
Dokumentace a uživatelská podpora
CakePHP má několik zdrojů informací. Jedním z nich je výborně zpracovaný API manuál. Dále je k dispozici manuál popisující začátky práce v Caku. Orientace v manuálu chvíli potrvá, ale po větším prozkoumání zde nalezneme téměř vše potřebné. Na oficiálním webu je k dispozici tutoriál „jak vytvořit vlastní blog“.
Jelikož je komunita okolo tohoto projektu velká, můžeme hledat rady také na IRC kanálu či na Google Groups. Na internetu rovněž nalezneme velké množství materiálů v češtině a také hotové projekty, ve kterých můžeme hledat inspiraci.
Ukázka zdrojových kódů
Jak již bylo řečeno výše, pohled se skládá z HTML a PHP, případně je možno použít také Smarty. Níže je zobrazena ukázka pohledu. Jednotlivé proměnné se předávají v kontroleru pomocí příkazu set (například $this->set('members', $members))
.
1 <?php foreach( $members as $member) { ?> 2 <tr> 3 <td><?php echo $member['Member']['ID'] ?></td> 4 <td><?php e($member['Member']['name']) ?></td> 5 <td><?php echo $member['Member']['type'] ?></td> 6 <td><?php echo $member['Member']['town'] ?></td> 7 <td><?php echo $html->link('edit', '/members/edit' . $member['Member']['ID'])." ".$html->link('uživatelé', '/users/index' . $member['Member']['ID']); ?></td> 8 </tr> 9 <?php } ?>
Funkce pro zpracování editovaných údajů – kontroler users:
1 function edit($id_user, $id_member) { 2 if(empty($this->data)) { 3 $this->pageTitle = 'Editace uživatele'; 4 $this->set('users', $this->User->find("id=$id_user")); 5 $this->set('id_mem', $id_member); 6 $this->render(); 7 } else { 8 $this->cleanUpFields(); 9 if($this->User->save($this->data, $id_user)) { 10 $this->Session->setFlash('Uživatel byl úspěšně upraven.'); 11 $this->redirect('/users/view/'.$id_member); 12 } else { 13 $this->Session->setFlash('Data se nepodařilo upravit.'); 14 $this->redirect('/users/view/'.$id_member); 15 }}}
Ukázka modelu:
1 class User extends AppModel 2 { 3 var $name = 'User'; 4 5 function save($data = null, $id) { 6 $this->id = $id; 7 $returnval = parent::save($data, false); 8 return $returnval; 9 } 10 }
Výsledky testů bez použití eAcceleratoru
Akce | Vzorky | Průměr [ms] | Median [ms] | Min [ms] | Max [ms] | Sm. Odch. [ms] | Modus [ms] |
---|---|---|---|---|---|---|---|
První test | |||||||
Zobrazení členů | 30 | 206 | 172 | 62 | 1078 | 187,29 | 63 |
Zobrazení uživatelů | 30 | 173 | 172 | 62 | 390 | 79,70 | 78 |
Editace uživatele | 30 | 198 | 187 | 78 | 625 | 131,72 | 94 |
Upravení dat | 30 | 483 | 360 | 141 | 3265 | 588,90 | 156 |
Celkem | 120 | 265 | 188 | 62 | 3265 | ||
Druhý test | |||||||
Zobrazení členů | 30 | 156 | 140 | 62 | 563 | 99,19 | 94 |
Zobrazení uživatelů | 30 | 165 | 140 | 78 | 359 | 78,03 | 110 |
Editace uživatele | 30 | 170 | 156 | 78 | 359 | 76,58 | 109 |
Upravení dat | 30 | 300 | 297 | 141 | 500 | 95,98 | 297 |
Celkem | 120 | 198 | 172 | 62 | 563 | ||
Třetí test | |||||||
Zobrazení členů | 30 | 125 | 125 | 62 | 250 | 44,83 | 125 |
Zobrazení uživatelů | 30 | 142 | 125 | 78 | 360 | 67,39 | 78 |
Editace uživatele | 30 | 148 | 141 | 62 | 312 | 56,52 | 125 |
Upravení dat | 30 | 318 | 297 | 141 | 828 | 141,76 | 188 |
Celkem | 120 | 183 | 141 | 62 | 828 |
Obr. 8. Průměrné časy zpracovávaných akcí v CakePHP bez eAcceleratoru
Paměťové nároky: 2867,82 kB
Akce | Průměrný čas [ms] |
---|---|
Výsledky testů s použitím eAcceleratoru
Akce | Vzorky | Průměr [ms] | Median [ms] | Min [ms] | Max [ms] | Sm. Odch. [ms] | Modus [ms] |
---|---|---|---|---|---|---|---|
První test | |||||||
Zobrazení členů | 30 | 47 | 16 | 15 | 766 | 133,66 | 31 |
Zobrazení uživatelů | 30 | 30 | 16 | 15 | 187 | 31,43 | 16 |
Editace uživatele | 30 | 25 | 16 | 15 | 47 | 11,63 | 16 |
Upravení dat | 30 | 58 | 47 | 31 | 141 | 22,86 | 47 |
Celkem | 120 | 40 | 31 | 15 | 766 | ||
Druhý test | |||||||
Zobrazení členů | 30 | 19 | 16 | 0 | 62 | 12,63 | 15 |
Zobrazení uživatelů | 30 | 26 | 16 | 15 | 47 | 13,55 | 16 |
Editace uživatele | 30 | 21 | 16 | 15 | 32 | 7,66 | 16 |
Upravení dat | 30 | 44 | 47 | 31 | 62 | 7,67 | 47 |
Celkem | 120 | 28 | 31 | 0 | 62 | ||
Třetí test | |||||||
Zobrazení členů | 30 | 37 | 16 | 15 | 485 | 83,49 | 16 |
Zobrazení uživatelů | 30 | 24 | 16 | 15 | 47 | 10,36 | 31 |
Editace uživatele | 30 | 18 | 16 | 15 | 47 | 7,10 | 16 |
Upravení dat | 30 | 46 | 47 | 31 | 94 | 13,55 | 47 |
Celkem | 120 | 31 | 31 | 15 | 485 |
Obr. 9. Průměrné časy zpracovávaných akcí v CakePHP s eAcceleratorem
Paměťové nároky:
Framework: 561,11 kB eAccelerator: 1996,80 kB Celkem: 2557,91 kB
Zhodnocení
CakePHP dosahuje velmi dobrých výsledků, jak s použitím eAcceleratoru, tak bez něj. Jeho paměťová náročnost není tak vysoká. Obsahuje velkou softwarovou výbavu a jeví se jako vhodný pro práci na velkých i malých projektech. Jeho nevýhodou je, že jsou vyvíjeny paralelně dvě verze, které nejsou navzájem plně kompatibilní. Z toho důvodu je lepší začít používat novější verzi, která je prozatím ve stádiu beta verze. Většina tutoriálů a dalších pomocných materiálů je však určena pro starší verzi 1.1.
Příklad webu postaveného na tomto frameworku: http://mark-story.com/
Další díl
V dalším díle seriálu se můžete těšit na testy frameworků CodeIgniter, Jelix a Kohana.