Adresářová struktura pro projekty v Zend Frameworku
Ve standardním inkubátoru je nýní návrh W. Slinclaira o struktuře adresářů projektů postavených na Zend Frameworku. Tenhle návrh je důležitý především pro Zend_Build pro buildění částí projektů z cmd.
Mně se obecně na projektech postavených nad Zendem nelíbí vkládání adresářů s modely na stejnou úroveň jako ty s controllery a views (v modulární struktuře). Model je z mého pohledu úplně jiná část než šablony či controllery, protože každá šablona je (téměř) vždy spojena s nějakou action metodou controlleru, zatímco metody daného modelu požívám v různých modulech. Třeba v administraci se může načítat jen jeden modul Články s CRUD controllerem a navazujícími šablonami, ovšem v uživatelské části pak budu chtít třeba na indexu vypisovat poslední tři vložené články a otázka je, kam pak mám model Články vložit, zda do modulu defeault či admin. Když si řeknu, že dám všechny modely, které se používají jak v default, tak v admin, do default, pak mi v admin modulu zbyde jen několik modelů. Proto mi připadá lepší dát adresář models na stejnou úroveň jako modules.
Další věc jsou soubory s překlady. Pro konkrétní projekty mi připadá dobré udělat jeden soubor pro jeden modul, které pak načte controller plugin podle daného modulu. Pro modulární krabicové řešení mi naopak připadá lepší vytvořit jen jeden soubor pro jeden controller + načítat globální soubor s překlady pro konkrétní modul (resp. pro konkrétní šablonu layoutu). Vznikne pak další hieararchie adresářů, ovšem nenačítá se mnohatisícový soubor, když potřebuji přeložit dvě hlášky.
Další zjednodušení přináší vytváření formulářů jako samostatných tříd zděděných ze Zend_Form. Podobně jako v případě souborů s překlady se vytváří další kopie adresářů, ovšem značně se tím zpřehlední controllery (nebo modely, pokud vytváříte instance tam).
A poslední věc je přepracování dispatcheru. Nelíbí se mi, jak všechny frameworky používají jednu třídu pro jeden controller. Více se mi líbí používání jedné třídy přímo pro jednu akci. Např. akce update u controlleru Clanky se tedy nebude volat jako metoda UpdateAction uvnitř /modules/admin/controllers/ClankyController.php, ale jako metoda index uvnitř třídy v souboru /modules/admin/controllers/clanky/UpdateAction.php. Jednak nebude potřeba načítat dlouhý controller kvůli zavolání 5 řádkové metody, ale můžu si vytvořit nějakou abstraktní třídu Update, od které se pouze daná metoda zdědí, což při klasické struktuře nejde (resp. jde, ale to bych pak musel mít dlouhý rodičovský controller a dětit všechny metody, i když je vůbec nepotřebuju a to mi nepříjde moc hezké).
Případné komentáře směřujte prosím na mail jakub.mrozek@gmail.com, díky.
|
29. 6. 2008 Ne 18.46 | Zend Framework |
| 184x
Novinky v Zendu
Dlouho jsem neměl více času pro sledování novinek v Zend Frameworku a následný import těch nejzajímavějších tady na weblog, což se dnes změnilo a v následujícím článku vám představím, co se v zendu chystá do připravované verze 1.6 a do budoucích verzí.
Verze 1.6, 1.3.2 a brzy následující 1.7 budou už velmi brzy, uzávěrka pro vývojáře je 30.6.
Nejspíš jste zaznamenali, že byl přepracován celý systém proposals a vznikly další knihovna s prefixem ZendX. V jejím inkubátoru bude dostupná knihovna Zend_Microformat s podporou pro hCard a Xfn. Zend_Microformat_hCard bude umožňovat vytváření vizitek v (X)HTML. Zrovna nedávno by se mi hodila pro kontaktní stránku Shopia, jakmile bude dostupná, tak ji hned implementuju. Formát xfn zase slouží pro definici vztahu k ostatním stránkám, to jako když odkážete na něčí blog, tak můžete k odkazu uvést, že se jedná o kamaráda, souseda ap. To nejspíš využijí jen nějaké komunitní stránky.
Velké vyznamenání se Zendu dostalo nedávno, když vývojáři z BBC oznámili, že pro nové stránky budou používat PHP & Javu, přičemž pro prezentační vrstvu použijí Zend Framework. Kdysi jsem o stránkách BBC četl, jedná se o extrémně zatížený server s vyšší návštěvností než jakýkoliv český web.
Do zendu se také dostal zajímavý nástroj pro kontrolu štábní kultury. Zhruba před rokem a půl jsem do wiki přidával proposal na tohle téma a po pár měsících se toho někdo ujal a dnes už je tento nástroj dostupný, funguje ve spolupráci s něčím z PEAR. Je v SVN v adresáři standard → tools → codingstandard.
Dále jste určitě zaznamenali spojenectví s javascriptovým frameworkem Dojo. V Zendu bude dostupných několik knihoven pro Dojo, třeba tam bude view helper, který dokáže nahrát konkrétní soubor frameworku Dojo do šablony.
Nově je také dostupný Code browser pro procházení zdrojáků online. Nevím, zda tam už nebyl dříve, všiml jsem si ho až nedávno.
Dobře také pokračuje nástroj pro vytváření souborů z příkazové řádky (Zend_Build & Zend_Console), ovšem předpokládám, že ještě nějaký čas dostupný nebude.
Do inkubátoru byl v minulých hodinách přenesena knihovna Zend_Text_Figlet, což je něco na způsob CAPTCHy, ovšem o něco přístupnější. Líbí se mi ale určitě více než klasická CAPTCHA. Brzy bude také dostupná knihovna Zend_Service_Recaptcha.
Nově bude také dostupný nástroj pro testování controllerů (link) od Matthew Weier O'Phinneyho.
Dále bude ustanovana výchozí struktura pro všechny adresáře v projektech postavených na Zend Frameworku, proposal najdete zde.
Pak bude v Zendu Zend_Db_Table_Plugin, který umožní třeba definovat akce, které se stanou před/po vložení do databáze ap. a action helper pro vícestránkové formuláře a mnoho dalších.
Pak bude sposta současných knihoven vylepšených o nové features (link).
Případné komentáře směřujte prosím na mail jakub.mrozek@gmail.com, díky.
|
24. 6. 2008 Út 19.44 | Zend Framework |
| 206x
Shopio je na světě!
S myšlenkou vytvořit „krabicové řešení“ eshopu jsem si pohrával už od poloviny roku 2005. Před rokem a půl dostala myšlenka konkrétní název Shopio a od konce minulého ruku se začalo tvořit. Před dvěma měsíci jsme spustili na Shopiu první projekt a dnes podle cca 6 měsíčního plánu došlo Shopio do své první verze.
Úvodní článek k vydání najdete na Shopio weblogu. Zcela nový je rovněž web Shopio.cz, kde si můžete vyzkoušet demoverzi uživatelské části i administrace (v grafice od Nuvia).
Shopio má spoustu vlastních nápadů. Asi nejzajímavější je ajaxové vkládání nového produktu do databáze, které je zcela odlišné od jiných eshopů. Na základě vybraných kategorií se nahrává šablona parametrů a podle vybraných hodnot pak různé kombinace variant. Vkládání nového produktu je vážně hodně hodně jednoduché, konkrétní výsledek pak můžete vidět třeba zde. Během editace se navíc data průběžně ukládají (jako třeba v gmailu), tzn., že pokud se „ukliknete“ po psaní dlouhého textu, nepříjdete o důležitá data. Pak je tam spostu ukrytých featurek jako automatické doplňování emailových adres (opět podobně jako v gmailu), inline editace, filtrování (u číselných hodnot v tabulkách je možné třeba zadat „>50“ pro výběr čísel větších než 50, definovat rozsah ap.). Všechna data jsou stránkovaná, je možné je setřídit podle různých sloupců, … brzy bude dostupné instruktážní video pro Shopio, kde uvidíte vše ostatní.
Každou hodinu se nahrávají na web demonstrační data, takže kdyby došlo k nenadálé změně, je to cronem.
Případné komentáře směřujte prosím na mail jakub.mrozek@gmail.com, díky.
|
23. 6. 2008 Po 23.09 | Shopio.cz |
| 215x
Tipy pro práci se Zend_Db III.
Poslední díl seriálu o Zend_Db je věnován vztahům mezi tabulkami a kaskádovým operacím.
Každý obal nad tabulkou v databází (potom třídy zend_Db_Table_Abstract) začíná definicí vztahů dané tabulky k ostatním vytvořením referenční mapy, definicí názvu tabulky ($_name) a závislých tabulek ($_dependentTables). Jednoduchým příkladem je vztah dvou tabulek orders pro objednávky a products pro produkty. V tabulce orders je sloupec product_id, která odkazuje na tabulku products.
class Product extends Zend_Db_Table_Abstract
{
protected $_name = ‚products‘;
protected $_dependentTables = array(‚Order‘);
}
class Order extends Zend_Db_Table_Abstract
{
protected $_name = ‚orders‘;
protected $_referenceMap = array(
‚Products‘ ⇒ array(
‚columns‘ ⇒ array(‚product_id‘),
‚refTableClass‘ ⇒ ‚Product‘,
‚refColumns‘ ⇒ array(‚id‘)
)
);
}
Hlavní tabulka definuje atribut $_dependentTables, závislá tabulka $_referenceMap. Products je název pravidla, columns určuje seznam sloupců závislé tabulky, které odkazují na hlavní tabulku, refTableClass je název třídy obalující hlavní tabulku a refColums je pole sloupců, na které se odkazuje.
Když budete chtít najít všechny objednávky, ve kterých figuroval daný produkt, pak to lze přes metodu findDependentRowset():
$product = new Product();
$data = $product->find(1)->current();
$orders = $data->findDependentRowset(‚Order‘);
Metoda také přijímá druhý parametr, který říká, které pravidlo použít (to kdyby byly tabulky propojeny přes vícero pravidel). Třetí nepovinný parametr umožňuje předat SQL dotaz omezující množinu vrácených výsledků. U relace 1:1 nemá žádné využití, nicméně u vztahu 1:N budete chtít třeba vrátit jen první tři výsledky ap., pak je to velmi užitečné.
Alternativně je možné využít magickou metodu __call() a volat metodu jako find<Trida>() nebo find<Trida>By<Pravidlo>():
$product = new Product();
$data = $product->find(1)->current();
$orders = $data->findOrder();
Podobné je to při vracení výsledků ze závislé tabulky. Pokud budeme mít tedy výpis objednávky a budeme chtít vypsat informace o objednaném produktu, pak to lze udělat takto:
$order = new Order();
$data = $order->find(1)->current();
$product = $data->findParentRow(‚Product‘);
Podobně je možné využít i v tomto případě magické metody přes pravidlo findParent<TableClass>() nebo findParent<TableClass>By<Rule>().
O něco málo složitější je definice many-to-many vztahu. Výše uvedené příklady nejsou moc z praxe, protože jedna objednávka může obsahovat mnoho produktů a naopak jeden produkt může být v mnoha objednávkách. Takže nová definice schéma:
class Product extends Zend_Db_Table_Abstract
{
protected $_name = ‚products‘;
protected $_dependentTables = array(‚OrderProduct‘);
}
class Order extends Zend_Db_Table_Abstract
{
protected $_name = ‚orders‘;
protected $_dependentTables = array(‚OrderProduct‘);
}
class OrderProduct extends Zend_Db_Table_Abstract
{
protected $_name = ‚shopio_orders_products‘;
protected $_referenceMap = array(
‚Products‘ ⇒ array(
‚columns‘ ⇒ array(‚product_id‘),
‚refTableClass‘ ⇒ ‚Product‘,
‚refColumns‘ ⇒ array(‚id‘)
),
‚Orders‘ ⇒ array(
‚columns‘ ⇒ array(‚order_id‘),
‚refTableClass‘ ⇒ ‚Order‘,
‚refColumns‘ ⇒ array(‚id‘)
),
);
}
//ziskavani dat $order = new Order();
$data = $order->find(1)->current();
$products = $data->findManyToManyRowset(‚Product‘, ‚OrderProduct‘);
Také pro many-to-many vztah je možné určit magické metody:
find<TableClass>Via<IntersectionTableClass>([Zend_Db_Table_Select $select]); find<TableClass>Via<IntersectionTableClass>By<Rule1> ([Zend_Db_Table_Select $select]); find<TableClass>Via<IntersectionTableClass>By<Rule1>And<Rule2> ([Zend_Db_Table_Select $select]);
takže výše uvedený příklad by s použitím magických metod vypadal takto:
$products = findProductViaOrderProduct();
Poslední feature je náhrada declarative referential integrity (DRI) pro databáze, které tohle neobsahují. Třeba u MySQL není možné definovat cizí klíče pro tabulky typu MyISAM, a tak když dojde ke smazání záznamů v jedné tabulce, bylo by fajn automaticky odstranit všechny závislé záznamy z ostatních tabulek. Zend Framework dokáže tento nedostatek některých databází nahradit.
Do pole $_referenceMap je potřeba přidat onUpdate nebo onDelete klíč s hodnotou self::CASCADE. Pokud pak zavoláte metodu delete() nebo save(), odstraní se/editují se všechny závislé záznamy.
Komentáře směřujte prosím na mail jakub.mrozek@gmail.com, díky.
|
12. 5. 2008 Po 20.06 | Zend Framework |
| 280x
Upozornění!
Články ze staršího weblogu najdete na adrese history.ronnieweb.net