Velký test PHP frameworků (2. díl)

28. 8. 2008
Doba čtení: 14 minut

Sdílet

V prvním díle seriálu jsme si řekli něco málo o frameworcích pro PHP, o jejich testování a mohli jsme se také dovědět jak si v testech vedly frameworky Akelos a CakePHP. Dnes se podíváme na zoubek dalším třem frameworkům. Jedná se o známé frameworky CodeIgniter, z něj vycházející Kohana a poněkud méně známý framework Jelix.

CodeIgniter

Jedná se o framework určený pro PHP 4.3.2 nebo novější. Aktuální verze 1.6.1 je ke stažení na internetové stránce http://codeig­niter.com. Jde o velmi jednoduchý, intuitivní framework, který je vyvíjen firmou, nikoliv komunitou.

Základní vlastnosti

  • Podpora databází MySQL (4.1+), MSSQL, PostgreSQL, Oracle, SQLite, ODBC. Pro práci s databází používá upravenou třídu Active Record. Tato „ORM“ třída však neumí pracovat s relacemi. Na internetu jsou k nalezení tutoriály popisující implementaci Doctrine do CodeIgniteru.
  • Najdeme zde několik užitečných pluginů pro práci s Excelem, captchou, generátory PDF, či geografické lokátory, které dle IP adresy určují pozici.
  • Pohledy jsou tvořeny klasickými inline zápisy PHP. Do jednotlivých pohledů můžeme includovat jiné části. Rovněž obsahuje vlastní template parser, díky kterému můžeme používat pseudo-proměnné (zápis v pohledu vypadá například takto: <title>{blog_ti­tle}</title>). V případě potřeby můžeme snadno implementovat šablonovací systém Smarty.
  • Validace probíhá v kontroleru, kde můžeme definovat jednoduchým zápisem i složitější pravidla (například: „trim|required|mat­ches[passconf]|md5“). Díky callbackům lze snadno do validace zapojit i vlastní funkce. Nevýhodou je, že validace není zabudována přímo do form helperu, tudíž je nutno zapsat ji samostatně.
  • Modely, které chceme v dané metodě používat, je třeba načíst pomocí funkce load.
  • Obsahuje standardní helpery.
  • Nastavení probíhá úpravou konfiguračních souborů. Nemá žádné speciální požadavky. Pro hezká URL je vyžadován mod_rewrite.

Dokumentace a uživatelská podpora

Dokumentace je, díky rozdělení na helpers, general topic, class reference, velmi přehledná a nalezneme v ní spoustu užitečných rad. Dále můžeme využít fórum či wiki. Při zběžném ohledání stránek jsem nenašel API referenci, což je možná vada na kráse celé dokumentace.

Na stránkách CodeIgniteru nalezneme dva video tutoriály, a to „návod na Hello World!“ a „vytvoření blogu za 20 minut“. Obě videa jsou dobře zpracovaná a jistě pomohou v začátcích. V prvním videu se seznámíme se základními adresáři a práci s pohledy a kontrolery. Druhý tutoriál ukazuje také práci s modely a databází.

Komunita kolem tohoto projektu je poměrně velká, proto není těžké nalézt nové hotové pluginy a helpery, či celé projekty. Několik návodů na CodeIgniter je k nalezení také v češtině. Na fóru nalezneme více IRC kanálů, včetně oficiálního kanálu.

Ukázka zdrojových kódů

Na ukázce můžete vidět vytvoření formuláře a inputu pomocí vestavěných helperů. Ukázka nepoužívá template parser.

1   <h1><?php echo $heading;?></h1>
2   <? echo form_open('users/editsend/'.$row['ID'].'/'.$row['id_member']); ?>
3   <table cellspacing = "10" border="1" cellpadding = "5">
4   <tr>
5   <td>Jmeno: </td>
6   <td><?php echo form_input(array(
7                'name'        => 'name',
8                'value'       => $row['name'],
9                'maxlength'   => '30')); ?>
10                <?=$this->validation->name_error; ?>
11  </td>
12  </tr> 

V ukázce kontroleru je začátek funkce zpracovávající odeslaný formulář.

1   function editsend($id, $m_id)
2   {
3       $data = array();
4       $data['name'] = $this->input->post('name');
5       $data['surname'] = $this->input->post('surname');
6       $data['phone'] = $this->input->post('phone');
7       $data['email'] = $this->input->post('email');
8
9       $this->load->library('validation');
10      $rules['name']  = "required";
11      $rules['surname'] = "required";
12      $rules['phone'] = "required";
13      $rules['email'] = "trim|required|valid_email";
14      $this->validation->set_rules($rules);
15      $this->validation->set_fields($data);
16
17      if ($this->validation->run())
18      {
19          $this->load->model('Users_model', 'model_users');
20          $this->model_users->Edit($id, $data)
21      }
22  } 

Zobrazení části modelu, který se stará o uložení dat při editaci uživatele.

1   class Users_model extends Model {
2       function Users_model()
3       {
4           parent::Model();
5       }
6       function Edit($id, $data){
7           $this->db->where('ID', $id);
8           $result = $this->db->update('users', $data);
9           return (bool) $result;
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 120 78 31 719 132,96 63
Zobrazení uživatelů 30 46 47 15 110 19,65 31
Editace uživatele 30 43 31 16 218 36,05 31
Upravení dat 30 413 172 78 2688 626,26 94
Celkem 120 155 63 15 2688    
Druhý test
Zobrazení členů 30 84 78 31 531 84,16 78
Zobrazení uživatelů 30 37 32 15 63 11,13 31
Editace uživatele 30 28 31 15 32 6,14 31
Upravení dat 30 132 125 79 297 46,98 94
Celkem 120 70 47 15 531    
Třetí test
Zobrazení členů 30 67 78 31 79 15,14 78
Zobrazení uživatelů 30 45 47 15 78 14,31 47
Editace uživatele 30 30 31 15 109 16,28 31
Upravení dat 30 148 140 78 656 102,37 94
Celkem 120 73 62 15 656    
frameworky2-obr10

Paměťové nároky: 1179,93 kB

Rychlosti práce s databází

Akce Průměrný čas [ms]
Výpis všech členů 4,33
Jméno člena 1,86
Všichni uživatelé člena 2,33
Načtení jednoho uživatele 6,22
Update dotaz 2,61
Celkem 3,47

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 23 16 15 109 19,09 16
Zobrazení uživatelů 30 14 16 0 16 3,93 16
Editace uživatele 30 14 15 0 16 3,88 15
Upravení dat 30 138 94 62 703 119,59 78
Celkem 120 47 16 0 703    
Druhý test
Zobrazení členů 30 18 16 15 32 5,85 16
Zobrazení uživatelů 30 14 15 0 16 3,88 15
Editace uživatele 30 13 16 0 16 5,34 16
Upravení dat 30 128 94 78 281 60,93 94
Celkem 120 43 16 0 281    
Třetí test
Zobrazení členů 30 17 16 0 63 9,71 16
Zobrazení uživatelů 30 13 15 0 16 4,66 15
Editace uživatele 30 13 16 0 16 5,89 16
Upravení dat 30 139 110 78 328 60,30 172
Celkem 120 46 16 0 328    
frameworky2-obr11

Paměťové nároky:

Framework:  270,12 kB
eAccelerator:   870,40 kB
Celkem: 1140,53 kB 

Zhodnocení

CodeIgniter má velmi malé paměťové nároky a dosahuje výborných rychlostí. Menší rychlost můžeme pozorovat při zápisu dat. Díky své jednoduchosti a výborně zpracované dokumentaci se hodí především pro uživatele začínající s frameworky. Díky mnoha dostupným rozšířením a své rychlosti může být bez problémů nasazen i na velké projekty.

Příklady webu postavených na tomto frameworku: http://codeig­niter.com/pro­jects/

Jelix

Jedná se poměrně nový framework (první beta verze byla vydána v lednu 2007), u kterého je třeba používat příkazový řádek k vytvoření aplikace, modulů a DAO objektů. Framework je určen pro PHP verze 5.2 a vyšší. Na internetové adrese http://jelix.org/ je k dispozici jeho verze 1.0.3. Jelix podporuje více výstupních formátů, kromě XHTML je zde také podpora pro XUL, RSS, ATOM, XML, PDF a další. Základní vlastnosti

  • Pro práci s databází používá Data Access Object (DAO). DAO modely je potřeba vytvořit pomocí příkazů v konzoli. Podporuje databáze MySQL (4.1+), PostgreSQL (8.0+), SQLite a PDO.
  • Mezi pluginy najdeme několik standardních, které známe z ostatních frameworků. Do výbavy Jelixu patří také jACL, což je správa práv v aplikaci. Bohužel jACL není zdokumentováno, takže nebylo ani otestováno.
  • Jelix má vlastní šablonovací systém jTpl. Tento systém využívá pro pohledy HTML v kombinaci s XUL a také pseudo-proměnné předané kontrolerem. Struktura se velmi podobá šablonovacímu systému Smarty.
  • Formuláře se ukládají jako XML soubory do speciálního adresáře. V tomto XML souboru se rovněž definují validační pravidla a chybové zprávy pro jednotlivé možnosti špatně zadaných dat.
  • V kontroleru můžeme přistupovat k libovolným modelům pomocí jDAO objektu.
  • Jelix neobsahuje žádné oficiální helpery. Za helpery by se daly považovat nějaké třídy sloužící k vytváření formulářů (používají XML), či třídy pro práci s URL.
  • Nastavení frameworku se provádí v konfiguračních souborech, které jsou vytvořeny při založení nového projektu. Pro běh jsou požadovány tyto rozšíření: dom, simplexml, pcre, session, tokenizer a spl.

Dokumentace a uživatelská podpora

Z dokumentace je jasně vidět, že se nejedná o zaběhnutý framework. Část dokumentace není dokončená, tak se často stane, že při procházení již konečně narazíte na hledaný výraz, avšak po kliknutí na něj se zobrazí jen chybové hlášení. Dokumentace je celkově dosti nepřehledná. K dispozici je také API reference.

V tutoriálech najdeme návod na vytvoření jednoduché aplikace, návod na konfiguraci databáze, práci s DAO a také ukázku vytváření formulářů.

Komunita kolem Jelixu není velká. Když zavítáme do fóra, nalezneme zde asi jen 20 příspěvků. Existuje zde také e-mailová konference a IRC, kde při náhodné návštěvě bylo pouze 8 lidí.

Ukázka zdrojových kódů

Ukázka pohledu:

1   <table>
2   {foreach $list as $users}
3   <tr>
4       <td>{$users->ID}</td><td>{$users->name} {$users->surname}</td><td>{$users->email}</td><td>{$users->phone}</td><td><a href="index.php?module=users&amp;id={$users->ID}&amp;action=edit">Edit</a></td>
5   </tr>
6   {/foreach}
7   </table> 

Jelix nemá model jako ostatní frameworky. Používá DAO soubor, který vidíme zde:

1   <property name="ID" fieldname="ID" datatype="autoincrement"/>
2   <property name="name" fieldname="name" datatype="string" required="true" maxlength="100"/>
3   <property name="street_number" fieldname="street_number" datatype="string" default="" maxlength="50"/>
4   <property name="street" fieldname="street" datatype="string" default="" maxlength="250"/>
5   <property name="town" fieldname="town" datatype="string" default="" maxlength="250"/>
6   <property name="ZIP_code" fieldname="ZIP_code" datatype="string" default="" maxlength="10"/> 

Funkce kontroleru obstarávající uložení dat:

1   function save() {
2       $mid = $this->param('memid');
3       $zaznam = jDao::createRecord('users~users');
4       $zaznam->ID = $this->param('id');
5       $zaznam->id_member = $mid;
6       $zaznam->name = $this->param('name');
7       $zaznam->surname = $this->param('surname');
8       $zaznam->phone = $this->param('phone');
9       $zaznam->email = $this->param('email');
10
11      $dao = jDao::get('users~users');
12      $dao->update($zaznam);
13      $rep = $this->getResponse('redirect', true);
14      $rep->action = 'users~default:index';
15      $rep->params = array('id' => $mid);
16      return $rep;
17  } 

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 81 47 31 859 145,47 47
Zobrazení uživatelů 30 53 47 31 94 17,40 47
Editace uživatele 30 63 47 31 203 37,15 47
Upravení dat 30 101 94 78 203 29,19 94
Celkem 120 75 62 31 859    
Druhý test
Zobrazení členů 30 66 47 31 531 87,44 47
Zobrazení uživatelů 30 47 47 31 94 13,06 47
Editace uživatele 30 48 47 31 109 14,28 47
Upravení dat 30 89 94 62 125 13,39 94
Celkem 120 63 47 31 531    
Třetí test
Zobrazení členů 30 57 47 31 125 26,56 47
Zobrazení uživatelů 30 48 47 31 78 11,65 47
Editace uživatele 30 46 47 31 94 14,05 47
Upravení dat 30 109 94 62 579 90,74 78
Celkem 120 65 47 31 579    
frameworky2-obr12

Paměťové nároky: 1283,31 kB

Rychlosti práce s databází

Akce Průměrný čas [ms]
Výpis všech členů 0,39
Jméno člena 0,31
Všichni uživatelé člena 0,59
Načtení jednoho uživatele 0,73
Update dotaz 1,42
Celkem 0,62

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 54 31 15 906 158,35 16
Zobrazení uživatelů 30 26 31 15 47 10,22 31
Editace uživatele 30 29 31 15 47 10,57 31
Upravení dat 30 58 47 31 125 20,64 47
Celkem 120 42 31 15 906    
Druhý test
Zobrazení členů 30 21 16 15 32 7,44 16
Zobrazení uživatelů 30 26 31 15 47 10,13 31
Editace uživatele 30 30 31 15 47 10,34 31
Upravení dat 30 61 47 31 406 64,87 47
Celkem 120 34 31 15 406    
Třetí test
Zobrazení členů 30 22 16 15 62 10,32 16
Zobrazení uživatelů 30 40 31 15 453 77,10 31
Editace uživatele 30 24 31 15 47 8,58 31
Upravení dat 30 51 47 31 78 10,60 47
Celkem 120 34 31 15 453    
frameworky2-obr13

Paměťové nároky

Framework:  371,21 kB
eAccelerator:   962,56 kB
Celkem: 1333,77 kB 

Zhodnocení

Jelix sice dosahuje výborných rychlostí a ani jeho paměťové nároky nejsou vysoké, ale vše nasvědčuje tomu, že se jedná o framework ve fázi vývoje. V dokumentaci jsou prázdná místa, nebo zde najdeme co bude mít Jelix v budoucnosti, což nám ovšem moc nepomůže. Nutnost použití příkazové řádky pro vytvoření aplikací a modelů je další přitěžující vlastností. Stejně tak nepřítomnost helperů či dalších funkcí, na které jsme zvyklí z jiných frameworků. Framework využívá XML pro tvorbu a validaci formulářů, či pro DAO modely. Tento přístup není obvyklý a může odradit potencionální uživatele.

Pokud bude pokračovat ve vývoji, implementuje standardní záležitosti (jako například helpery) a zlepší svou dokumentaci, tak se stane použitelným. V této fázi bych jej nedoporučil pro realizaci jakéhokoliv projektu.

Příklad webu postaveného na tomto frameworku: http://www.over-blog.com/

Kohana

Dalo by se říct, že tento framework je jistou verzí CodeIgniteru, napsanou čistě pro PHP 5. Dalším rozdílem je, že jej nevyvíjí firma, jak je tomu u CodeIgniteru, ale je vyvíjen komunitou. Verze 2.1.1 je ke stažení na http://kohanap­hp.com/. Dále na SVN můžeme nalézt části verze 2.1.2, na jejíž kompletní vydání se stále čeká. Některé metody jsou v těchto dvou verzích rozdílné, tudíž je, při přechodu na novější verzi, potřeba pamatovat na jejich změnu. Kohana je plně kompatibilní s UTF-8 a obsahuje rovněž nástroje pro práci s tímto kódováním.

Základní vlastnosti

  • Podpora databáze MySQL, PostgreSQL a na SVN je dostupný také řadič pro PDOSqlite. Obsahuje ORM knihovnu, díky níž můžeme snadno přistupovat k datům v databázi.
  • Mezi vybavením můžeme, kromě standardních pluginů, najít také knihovnu pro online platby (například PayPal a další), či knihovnu pro práci s komprimovanými archívy. Velice užitečný je forge modul, který umožňuje jednoduché generování formulářových prvků, včetně jejich přímé validace. Knihovna pro práci s obrázky nám umožní jednoduché otočení obrázku, změnu velikosti a další základní operace.
  • Pro prezentaci dat používá kombinaci standardního PHP a HTML. V případě potřeby je možno implementovat Smarty. Oproti CodeIgniteru zde není dostupný template parser.
  • Kromě validační knihovny obsahuje také validační helper. V případě použití klasických formulářů je třeba nadefinovat validační pravidla samostatně. Při použití forge modulu se však definují validační pravidla přímo při tvorbě formuláře, takže se poté již nemusíme o nic starat. Validace je možno rozšířit vlastními callbacky.
  • V kontroleru můžeme zavolat jakýkoliv existující model a poté lze využívat všech jeho funkcí. Díky ORM není problém pracovat s relacemi a dostat z databáze například člena, kterému patří daný uživatel (stačí mít v modelu uživatelů nadefinováno belongs_to member).
  • Obsahuje helpery, na které jsme zvyklí z jiných frameworků. Můžeme zde mimo jiné nalézt helpery pro práci se soubory (spojování souborů, vynucené stahování a další), nebo také pro odesílání e-mailů.
  • Nastavení se provádí překopírováním požadovaných konfiguračních souborů do složky aplikace a jejich následnou úpravou. Pro správný běh všech komponent jsou požadována některá rozšíření, kterými jsou iconv, mcrypt, SPL a PCRE zkompilováno s parametrem –enable-utf8. Více na ].

Dokumentace a uživatelská podpora

Dokumentace je zpracována velmi přehledně a díky rozdělení na tématické celky v ní lehce najdeme požadované informace. Chybějící API reference se dá lehce vygenerovat pomocí vestavěného modulu Kodoc.

Na stránkách nalezneme hned tři video tutoriály. První dva ukazují základní práci s frameworkem – vypsání „Hello World!“. Poslední z nich je zaměřen na práci se soubory médií a CSS. Dále jsou zde tutoriály, které ukazují, jak vytvořit vícejazyčný web či jak odstranit index.php z URL adresy.

Komunita kolem frameworku je velmi aktivní, díky tomu vycházejí opravy drobných chybiček rychle po jejich nahlášení a nejaktuálnější verze je stále dostupná na SVN. Spoustu odpovědí nalezneme na fóru a pokud potřebujeme nějakou tu radu, najdeme pomoc na IRC kanálu, kde často zastihneme vývojáře i samotného vedoucího projektu, kteří ochotně poradí.

Ukázka zdrojových kódů

Pohled se skládá ze standardního PHP (s použitím helperů) a HTML. Formulář je tvořen pomocí forge modulu v kontroleru.

1   <h2><?php echo  url_lang::lang('texts.Editation of member').' '.$member_data->name ?></h2><br />
2   <?php echo  html::anchor(url_lang::base().'members/show/'.$member_data->member_id,url_lang::lang('texts.Back to this member.')) ?>
3   <br />
4
5   <?php echo $form?> 

Model využívající ORM knihovny:

1   <?php
2   class User_Model extends ORM {
3       protected $belongs_to = array('member');
4       protected $has_many = array('jobs');
5   } ?> 

Kontroler obstarávající vytvoření formuláře pomocí forge modelu, validaci dat a jejich následné uložení.

@%&@
1   $form = new Forge(url_lang::base().'users/edit/'.$user_id, '', 'POST', array('id' => 'article_form'));
   2 

3   $form->group('')->label(url_lang::lang('texts.Basic informations'));
   4   $form->input('username')->label('username:')->rules('required|length[3,50]')->callback(array($this, 'valid_username'))->value($user_model->login);
   5   $form->input('name')->label('name:')->rules('required|length[3,30]')->value($user_model->name);
   6   $form->submit('submit')->value('Edit');
   7   special::required_forge_style($form, ' *', 'required');
   8         

9   if($form->validate())
   10  {
   11      $form_data = $form->as_array();
   12      $user_data = new User_Model($user_id);
   13      foreach($form_data as $key => $value)
   14      {
   15          $user_data->$key = htmlspecialchars($value);
   16      }
   17      if ($user_data->save())
   18      {
   19          $this->session->set_flash('message', 'User successfully updated.');
   20      }
   21      else
   22      {
   23          $this->session->set_flash('message', 'Error - cant update user.');
   24      }
   25      url::redirect(url_lang::base().'users/show/'.(int)$user_id);
   26  }

@%&@

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 109 78 31 891 153,57 78
Zobrazení uživatelů 30 49 47 31 94 20,14 47
Editace uživatele 30 47 31 31 188 34,64 31
Upravení dat 30 346 204 94 2093 484,33 235
Celkem 120 138 63 31 2093    
Druhý test
Zobrazení členů 30 66 63 31 93 14,76 78
Zobrazení uživatelů 30 40 31 31 63 12,73 31
Editace uživatele 30 30 31 16 32 2,76 31
Upravení dat 30 170 140 94 750 116,24 109
Celkem 120 76 62 16 750    
Třetí test
Zobrazení členů 30 74 78 47 172 20,01 78
Zobrazení uživatelů 30 43 47 31 63 13,83 31
Editace uživatele 30 34 31 31 125 17,00 31
Upravení dat 30 180 171 109 703 109,74 110
Celkem 120 83 63 31 703    
frameworky2-obr14

Paměťové nároky: 1324,73 kB

Rychlosti práce s databází

Akce Průměrný čas [ms]
Výpis všech členů 4,87
Jméno člena 2,15
Všichni uživatelé člena 2,41
Načtení jednoho uživatele 7,00
Update dotaz 3,15
Celkem 4,58

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 27 16 15 157 25,56 16
Zobrazení uživatelů 30 26 31 15 32 7,13 31
Editace uživatele 30 16 16 0 32 7,59 16
Upravení dat 30 173 188 93 312 57,58 203
Celkem 120 60 31 0 312    
Druhý test
Zobrazení členů 30 21 16 15 32 7,70 16
Zobrazení uživatelů 30 23 31 0 32 8,90 31
Editace uživatele 30 17 16 0 32 8,39 16
Upravení dat 30 165 156 93 297 62,72 109
Celkem 120 57 31 0 297    
Třetí test
Zobrazení členů 30 21 16 15 32 7,47 16
Zobrazení uživatelů 30 24 31 0 32 8,58 31
Editace uživatele 30 17 16 0 31 6,07 16
Upravení dat 30 179 141 93 422 86,01 125
Celkem 120 60 31 0 422    
frameworky2-obr15

Paměťové nároky

Framework:  346,68 kB
eAccelerator:   962,56 kB
Celkem: 1309,24 kB 

Zhodnocení

Díky své jednoduchosti a výborné dokumentaci je Kohana ideální pro začínající uživatele. Není to jen jednoduchý framework, ale rovněž mocný. Po přidání několika komponent jej, díky jeho rychlosti a nízkým paměťovým nárokům můžeme využít i pro velké projekty. Komponenty pro tvorbu formulářů šetří mnoho času a rovněž tak komponenta pro tvorbu výpisů dat do tabulek, kterou můžeme najít na fóru. Pokud se podíváme na výsledky testů, vidíme že Kohana velmi dobře zvládá zpracovávat požadavky i bez přítomnosti eAcceleratoru. Vyšší časy můžeme sledovat při úpravě dat.

ict ve školství 24

Jednou z věcí, která by se dala vytknout je neúplná kompatibilita současné verze s nově vyvíjenou. Na všechny nekompatibilní změny je upozorňováno v dokumentaci. Příklad webu postaveného na tomto frameworku: https://freene­tis.slfree.net/cs/lo­gin

To bylo pro dnešek vše. V příštím díle nás čekají frameworky Fuse, Prado a Qcodo.