Nette addons, konvence a architektura aplikace
- juzna.cz
- Člen | 248
Tak nette/addon-installer uz mi pekne pridava nastaveni do configu.
Zitra jeste doresim kopirovani tech assetu, ale to by melo jit taky docela
jednoduse.
Nasledne bych zalozil meta-addony: jQuery, jQuery UI, netteForms. Ty budou moci byt pouzity v zavislostech jinych addonu, coz je casto potreba.
Editoval juzna.cz (1. 8. 2012 16:40)
- Pavel Kouřil
- Člen | 128
Zrovna jQuery, jQuery UI apod., je AFAIK doporučované includovat z CDN. Má to opravdu tedy smysl?
A přinejhorším si může addon s sebou vevnitř skrytě jQuery tahat a pokud nebude načteno z CDN, tak si jej to načte samo?
- juzna.cz
- Člen | 248
Tak me napadlo udelat jeden velkej addon nette/extras se vsema moznyma javascriptama a stylama, ktery se casto vyskytujou. Addon, ktery by chtel mit zavistlosti napr na jQuery, tak by to udelal pomoci zavislosti na tento balicek. Priklad addonu – zajimava sekce require a extra:
"require": {
...
"nette/extras": "@dev"
},
"extra": {
"nette-addon": {
...
"extras": [ "jQuery", "jQuery-UI", "netteForms" ]
}
}
V nette/extras pak bude custom-installer, ktery zpracuje podsekci extras a nainstaluje polozky v ni obsazene.
- LeonardoCA
- Člen | 296
juzna.cz:
Nad něčím takovým jsem taky přemýšlel, jak jsem četl v posledních
dnech příspěvky tady, ale nemám zkušenost s composerem, jen to co jsem
letmo přečetl – nevím nejlepší řešení – ale mám pár nápadů
k diskuzi.
Chtělo by to aby takový addon uměl:
- Možnost stahování js knihoven z CDN s fallbackem na lokální verzi.
- Nějak specifikovat závislosti jiných addonů na konkrétní verzi například jQuery. A následně nějak zajistit ošetření konfliktů verzí jQuery pokud by addony vyžadovaly různé verze jQuery. Tohle vidím jako dost komplexní problém.
- Mohl by buď přímo spolupracovat s Webloaderem pokud by byl zahrnut v addonech, nebo by instalátor mohl automaticky kopírovat js knihovny do adresáře www/assets/<library_name> (je-li to možné realizovat)
- Aby se dal bod 3. realizovat jednoduše, chtělo by to zavést pravidlo, že všechny takové knihovny budou v adresáři assets tj. např
www/assets/jQueryUI
www/assets/datatables
vnitřní podadresáře pak mohou být standartně js/,css/,images/ ale to už
není podstatné, protože relativní cesty mohou být libovolné, záleží na
knihovně
Editoval LeonardoCA (1. 8. 2012 13:21)
- juzna.cz
- Člen | 248
Pozor, na vyreseni assetu se musi vyresit dve veci: (a) mit asset k dispozici a (b) includnout ho do stranky. Na to druhe uz asi bude potreba WebLoader, jinak nevim, jak to udelat bez nej.
LeonardoCA napsal(a):
1. Možnost stahování js knihoven z CDN s fallbackem na lokální verzi.
To by byla vec addonu nette/extras, ktery by si ve svem custom installeru udelal, co by bylo potreba. Momentalne mam udelane, ze
- asset lokalne zkopiruje do
www/temp/
- prida ho do sekce assets v
addons.json
, na coz zareaguje WebLoader a includne ho do hlavicky stranky.
2. Nějak specifikovat závislosti jiných addonů na konkrétní verzi například jQuery. A následně nějak zajistit ošetření konfliktů verzí jQuery pokud by addony vyžadovaly různé verze jQuery. Tohle vidím jako dost komplexní problém.
Pravda, to asi bude slozite. Nejjednodussi by asi bylo mit addon jQuery a konflikty mezi verzema by pak vyresil sam composer. Pak by se zavislost na definovala klasicky v composer.json v sekci require.
3. Mohl by buď přímo spolupracovat s Webloaderem pokud by byl zahrnut v addonech, nebo by instalátor mohl automaticky kopírovat js knihovny do adresáře www/assets/<library_name> (je-li to možné realizovat)
Ano, to ted jiz mam hotove. JavaScripty (a CSS) neni nutne vykopirovavat, WebLoader si je spoji. U NiftyGridu mi to funguje pekne.
4. Aby se dal bod 3. realizovat jednoduše, chtělo by to zavést pravidlo, že všechny takové knihovny budou v adresáři
www/assets/
…
Ano, mam stejny nazor. Zatim to davam do www/temp/
coz je
vychozi cesta pro WebLoader. Idea je ale stejna.
Editoval juzna.cz (1. 8. 2012 16:42)
- LeonardoCA
- Člen | 296
Super, směr se mi líbí.
Ti co nepoužívají WebLoader by si pro začátek museli přidat požadované js,css ručně a měli by to zjednodušené tím, že by cesty byly jednotné.
- juzna.cz
- Člen | 248
Juan napsal(a):
Tak dneska jsem měl konečně chvilku času, tak jsem septal jednoduchou první představu v podobě pull requestu.
Take chci mit addony minimalisticke a co nejjednodussi, ostatne tak jako je delane cele Nette. Proto ti to zhodnotim jednoduse: Proc? Proc kazda trida/metoda, co tam mas? Je potreba? Neslo by ji vyhodit a udelat to bez ni?
Konkretneji:
- proc musi mit kazdy addon vlastni tridu
TestAddon
? Neslo by to bez ni? - proc ma dostavat DI Container? At si rekne jen o to, co opravdu chce.
- proc ma jmeno? Nebude pro pouziti stacit jmeno z composeru? Nebo jeste lepe jen interfaces?
- proc ma tolik callbacku? Nestaci, aby si je registroval sam na prislusna mista, kdyz bude potrebovat?
- je potreba AddonManager? Potrebuji mit v aplikaci pristup k samotnym addonum? Nestaci, kdyz se kazdy zaregistruje, kam ma?
Neber prosim mou kritiku jako nejaky utok proti tobe. Pokud mas argumenty, rad je vyslechnu, prodiskutuju a budu je zastavat. Stejne tak budu rad za stejnou kritiku proji memu navrhu. Diky
- Filip Procházka
- Moderator | 4668
Nevím jestli se Juan inspiroval přímo u mě, nebo u Symfony, ale Bundles se mi líbí. Něco si o tom přečti :)
- juzna.cz
- Člen | 248
Tak, trosku jsem to zrefaktoroval a vse vyclenil do samostatneho Configuratoru, kde je mozne jednoduse pridat nove podporovane sekce:
- sekce config-extensions zavola metodu registerSectionConfigExtensions
- sekce assets metodu registerSectionAssets
- …atd
Diky tomu uz to funguje i bez jakehokoliv hacku do Nette a na posledni verzi (2.0.4). Jedine zmeny oproti standardnimu sandboxu jsou:
- pouziti autoloaderu z composeru misto NetteLoaderu a RobotLoaderu
- pouziti pretizeneho Configuratoru
- nacteni config souboru
addons.neon
- css + javascript je v
@layout.latte
renderovan pomoci WebLoaderu, aby addony mohly jednoduse pridavat svoje assety
Vice addonu
Nyni by bylo potreba predelat vice addonu do teto pobody (composer + custom-installer), spravne nastavit zavislosti, otestovat je a pridat je na packagist. S tim se zaroven objevi potreba novych konfiguracnich sekci (extension pointu), ktere tedy bude potreba pridat do Configuratoru.
Rad bych timto pozadal komunitu o pomoc. Pokusim se co nejvice radit na Nette chatu, jabberu nebo pres email ci forum vsem zajemcum. Jakakoliv iniciativa vitana! Dekuji za podporu
- Patrik Votoček
- Člen | 2221
Symfony Bundles a Kdyby Packages
Mě se to nelíbí z jednoho prostého důvodu je to hodně Symfony-way a Symfony-way nemám rád (tady uděláme takovou a makovou třídu, tady takovou a makovou metodu … protože tohle by přeci mohl někdy někdo potřebovat!) ostatně to je důvod proč dělám v Nette a né v Symfony.
Teď jsem asi trochu vyvolal flame co? Sorry :-)
juzna.cz napsal(a):
Nyni by bylo potreba predelat vice addonu do teto pobody
Moc brzo nech to trochu uzrát. Nikomu se to pak nebude chtít předělávat pokud dojde k nějaké změně.
… a pridat je na packagist
Ne jenom to ne nebo nás z packagitu poženou vydlema. Nové https://addons.nette.org budou samy repozitářem pro composer kde o maximum věcí postará právě samo https://addons.nette.org.
Máme v plánu v brzké době tento projekt dotáhnout alespoň do stádia betaverze (pravděpodobně ještě teď v Srpnu proběhne další hackathon.
Co se týká mě tak ač se mě juznovo myšleka líbí a hodně zamlouvá tak absolutně odepisuje lidi, kteří nechtějí/nemůžou/nepoužívají/neumějí používat composer.
Má ideální představa je taková:
1. Člověk nepoužívající composer
Stáhne addon rozbalí do libs a přidá řádek do configu
common:
addons:
- WebLoader\Addon
- VisualPaginator\Addon
2. Člověk používající composer
Přidá řádek do composer.json a spustí
composer update
- Patrik Votoček
- Člen | 2221
Jako největší problém vidím již zmiňované CSS,JS a Obrázky a hlavně závyslost na nějaké verzi JS knihovny (jQuery, Angular.js, …). Obávám se že né všichni chtějí používat WebLoader nebo Assetic
- LeonardoCA
- Člen | 296
Patrik Votoček:
souhlas, mělo by to jít i bez composer
Jako největší problém vidím již zmiňované CSS,JS a Obrázky a hlavně závyslost na nějaké verzi JS knihovny (jQuery, Angular.js, …). Obávám se že né všichni chtějí používat WebLoader nebo Assetic
3. cesta je ručně – každý popis addonu by měl stejně v dokumentaci obsahovat seznam js a css souborů, které automaticky nebo volitelně přidá a kdo nepoužívá to ani ono, tak si ručně přidá tyto soubory jak bude chtít.
nápad: zmiňovaný addons.nette.org by mohl umět toto vyčíst z composer.json, css asi nějak jinak a zobrazit automaticky formou dokumentace/návodu. Autor addonu by nemusel tuto část popisovat ručně…
- Filip Procházka
- Moderator | 4668
Patrik Votoček napsal(a):
Symfony Bundles a Kdyby Packages
Mě se to nelíbí z jednoho prostého důvodu je to hodně Symfony-way a Symfony-way nemám rád (tady uděláme takovou a makovou třídu, tady takovou a makovou metodu … protože tohle by přeci mohl někdy někdo potřebovat!) ostatně to je důvod proč dělám v Nette a né v Symfony.
Ale kdepak, Symfony way je akademická cesta (ukecanější, ale pořád to má svůj smysl). To co popisuješ je Zend cesta ;)
Editoval HosipLan (1. 8. 2012 20:23)
- juzna.cz
- Člen | 248
Ted jsem se zasekl u addonu watchdog, u ktereho se registruje custom error logger. To samotne je easy, proste zavolam statickou metodu. Ta chce ale jako argument sluzbu, kterou snadno doplnime autowiringem. To je funkcni.
Problem 1: kdyz pridam addon, ale pozadovana sluzba neni definovana (coz
neni), configurator spadne a aplikace nejede. Nevim, co s tim.
Zde by se asi hodilo sice addon mit (ve filesystemu), ale nemit jej aktivovany
(v aplikaci).
Problem 2: nevim, jak podstrcit sluzbu jinak nez autowiringem – coz neni vzdy mozne nebo vhodne.
- juzna.cz
- Člen | 248
Patrik Votoček napsal(a):
Co se týká mě tak ač se mě juznovo myšleka líbí a hodně zamlouvá tak absolutně odepisuje lidi, kteří nechtějí/nemůžou/nepoužívají/neumějí používat composer.
To vubec neni pravda. Instalaci bude mozne stale provest starym zpusobem a vse nakopirovat a nastavit rucne. Ja se toto rucni nastavovani pouze snazim zautomatizovat pomoci (a) nette-addon-installeru a (b) addon configuratoru.
Clovek NEpouzivajici composer:
- stahe addon a rozbali do libs
- zkopiruje assety na spravna mista
- zaregistruje addony na spravna mista, tak jako to bylo do ted
Posledni bod by se dal nahradit necim jako ComposerExtension (pojmenovali bychom to treba NotComposer), ktery by natahl informace z composer.json v addonech, ktere by ten soubor stejne mely.
Kazdopadne, moznost nainstalovat addon i bez composeru musi existovat, s tim pocitam.
… závislost na nějaké verzi JS knihovny (jQuery, Angular.js, …)
To bude problem i pri manualni instalaci, ne?
Obávám se že né všichni chtějí používat WebLoader nebo Assetic
Samozrejme, neni problem. V tom pripade nette/addon-installer pouze
zkopiruje assets na dohodnuta mista
(WWW_DIR/assets/<addonNane>
) a do @layout.latte
uz si ho clovek doplni sam.
- Patrik Votoček
- Člen | 2221
juzna.cz napsal(a):
To vubec neni pravda. Instalaci bude mozne stale provest starym zpusobem a vse nakopirovat a nastavit rucne. Ja se toto rucni nastavovani pouze snazim zautomatizovat pomoci (a) nette-addon-installeru a (b) addon configuratoru.
3. zaregistruje addony na spravna mista, tak jako to bylo do ted
Ano ale mě jde o právě o tento bod jsem raději pro přidání jednoho řádku na jedno místo než na X řádků na X míst. Což imho tebou navrhované řešení vůbec neřeší a to je to na co jsem narážel.
… závislost na nějaké verzi JS knihovny (jQuery, Angular.js, …)
To bude problem i pri manualni instalaci, ne?
Proto je to taky jako poznámka pod čarou…
- juzna.cz
- Člen | 248
@Vrtak: Pokud bude addon ve formatu nette-addon (pro
nette/addon-installer), pak je mozne jej nainstalovat manualne tak, ze
do config.neon
do sekce addons pridam adresar addonu (nebo
primo cestu k composer.json z onoho addonu).
Udelala by se nejaka CompilerExtension, ktera by z takto
nainstalovanych addonu nacetla composer.json, z toho sekci
extra.nette-addon a podle toho by addon zaregistrovala na prislusna
mista, tak jako to dela instalator ted. Jediny rozdil, ze by to nacital primo ze
zdrojovych json souboru a ne z predzpracovaneho addons.neon.
Pokud by v addonu byly nejake assety, ktere se musi vykopirovat jinam, tak ty by se holt musely vykopirovat rucne. S tim asi nic nenadelame.
Editoval juzna.cz (2. 8. 2012 0:37)
- Jan Jakeš
- Člen | 177
@juzna.cz: Já jsem především rád, že ses do toho pustil a rozproudil tady diskusi, mně se to nepodařilo :)
Za tou „Symfony/Kdyby way“ si poměrně stojim, i když je pravda, že např. místo připravených callbacků by si je addon mohl registrovat sám. To ale vyžaduje větší úpravy Nette, registrovat callback do životního cyklu aplikace sice jde přes DI, ale dost ošklivě.
Jsem zvědavej, kam se vyvine tvá cesta, zatím nejsem přesvědčen, že to bude dostatečně universální, ale uvidíme. Podle mě není addon každá PHP knihovna, která jen používá něco z Nette\Utils nebo Nette\Object. Taková knihovna samozřejmě z aplikace nepotřebuje nic a na tu pak vypadá moje řešení přehnaně komplikovaně. Každopádně já budu celý srpen mimo civilizaci, takže vývoj sledovat nebudu a jsem zvědav, kam se to za tu dobu posune :)
Editoval Juan (2. 8. 2012 10:44)
- echo
- Člen | 134
Juznovo řešení assetů mi připadá jako overkill. Proč řešit assety composerem? Ten má addon stáhnout a maximálně třeba zaregistrovat do addons.neon. Tam by bylo pole s názvi tříd zastřešující Addony.
A byly by tam uvedeny jen Addony, které něco potřebují. Ať už assety, routování, DI. Vše by se mělo řešit pomocí odkazování. To znamená nic nikam automaticky neregistrovat, nic neassetovat a podobně.
Každý uživatel by měl mít možnost zajistit si a uzpůsobit si vlastním potřebám (Nette-way). Odkazováním myslím například metody:
getCompilerExtension() {
return new NetteExtension;
}
getAssets() {
return array(
'js' => array(ABSOLUTE_PATHS),
'css' => ...
);
}
Když si vyberu použití webloaderu, rozparsuju addons.neon, iteruju nad třídami a volám. Například:
foreach(Neon::decode(file_get_content(ADDONS_NEON) as $className) {
$class = new $className;
if($class instanceof IAssets) {
$assets = $class->getAssets();
foreach($assets['js'] as $asset) {
$container->webloader->jsFileCollection->addFile($asset);
}
}
}
Konvencí by bylo jen několik interfaců a každý addon by implementoval jen to, co potřebuje. (ICompileable, IAssets, IRouteable, …)
A tak podobně. Nejsem proti vytvoření implicitního řešení ve formě AddonsManageru ala Kdyby packages, sám jsem se inspiroval, ale nic nikomu, prosím, nevnucovat.
Editoval echo (2. 8. 2012 14:24)
- LeonardoCA
- Člen | 296
echo: Assets je potřeba řešit composerem, aby bylo možné řešit závislosti na javascriptových knihovnách, Když už se závislosti řeší composer, měl by řešit všechny – jinak by řešení závislostí bylo poloviční.
- hrach
- Člen | 1838
Odmitam nastrojem pro php resit js. S tim jdete nekam. Patrikova poznamka se mi libi, jde (mi) o to zjednodusit workflow i bez composeru. Budu nanejvys spokojen, kdyz mi composer update stahne nejnovejsi verzi se zavislostmi. Pridat do konfigu potrebnou sluzbu uz si zvladnu sam. Dekuji, muzete se posadit :)
- juzna.cz
- Člen | 248
@echo, @hrach: assets jsou jen jedna mala cast meho obecneho reseni. Jeste bych to vsak rozdelil na dve casti:
(a) Common assets neboli knihovny/frameworky atd. Prikladem budiz jQuery, Prototype, MooTools, jQuery UI, Twitter Bootstrap, … a mnoho dalsich. Zde se mi to take moc nelibi, jde spise o experiment o to dotahnout automatizaci do konce. Spise se take klonim k nazoru, ze to nebude spravna cesta, proto je to momentalne vyresene pouze zlehka a navic je to od vlastniho nette/addon-installer kompletne dekomponovane do nette/extras (ktery muze byt optional, nebo jej nakonec treba muzeme uplne zrusit).
V samotnem addonu je momentalne pouze drobna
zminka, aby zavislost na jQuery byla napsana aspon
nekde: "extras": [ "jQuery", "jQuery-UI" ]
Nicmene, jak rikam, highly experimental!
(b) Addon assets neboli javascript/css/obrazky pro konkretni addon. Napriklad NiftyGrid ma k sobe take styly, javascripty a obrazky.
Vsechny tyto assets je potreba (a) vykopirovat nekam do WWW_DIR
a (b) includnout je do hlavicky. Prvni muze udelat composer, druhe WebLoader
(pokud je nainstalovan). Klidne to ale clovek muze udelat manualne, pokud ma
naladu.
Reseni techto assetu installerem mi dava smysl.
Registrace addonu bych radeji videl deklarativne, tedy v config souboru. Tento soubor muze uzivatel vytvorit rucne, nebo mu ho muze installer generovat, pokud je uzivatel liny/pohodlny.
Druha moznost je registrovat addony imperativne, tzn ze se zavola nejaka matoda, ktera udela co je potreba. Ale to uz se neda tak pekne managovat. Kdyz by si chtel nekdo udelat klikatko na editaci, tak to uz nepujde tak pekne jako s editaci configu.
Ad overkill – prave naopak, snazim se o minimalisticke reseni. Mas jednoduchy addon, co potrebuje zaregistrovat extension metodu? Neni potreba delat dalsi novou tridu, staci poznamka v composer.json.
Naroky na tvurce addonu jsou tedy minimalni.
Ad univerzalnost – vzdy je mozne pridat jakoukoliv inicializacni metodu a udelat si tam, cokoliv kdo uzna za vhodne.
Editoval juzna.cz (2. 8. 2012 15:15)
- echo
- Člen | 134
LeonardoCA napsal(a):
echo: Assets je potřeba řešit composerem, aby bylo možné řešit závislosti na javascriptových knihovnách, Když už se závislosti řeší composer, měl by řešit všechny – jinak by řešení závislostí bylo poloviční.
Nesouhlasím, že to má mít na starosti Composer. Moje řešení:
class PackageA implements IAssets {
public static function getAssets() {
return array(
'js' => array(JQUERY_PATH)
);
}
}
class PackageB implements IAssets {
public static function getAssets() {
return array(
// pouze nástin, v reálu by samozřejmě potřebovalo upravit
'js' => array( PackageA::getAssets() ) // závislost - pouze uvést v composer.json závislost na PackageA
);
}
}
Závislost vyřešená, každý slušnější AssetsManager nepřidá jeden soubor vícekrát. Musely by se udělat balíčky/addony pro jquery, které by sice byly triviální, ale byl by v tom pořádek. A hrach by byl spokojen, protože by si to vyřešil po svém a žádné getAssets by ho nezajímalo.
juzna.cz napsal(a):
Druha moznost je registrovat addony imperativne, tzn ze se zavola nejaka matoda, ktera udela co je potreba. Ale to uz se neda tak pekne managovat. Kdyz by si chtel nekdo udelat klikatko na editaci, tak to uz nepujde tak pekne jako s editaci configu.
Naopak mi to připadá pohodlnější protože mám vše na jednom místě addons.neon.
Konfigurace v neonu deklarativně by měla být volitelná, pracujeme v php ne v neonu. Dokázal bych si ji představit v implicitním addons manageru.
- echo
- Člen | 134
juzna.cz napsal(a):
Ad overkill – prave naopak, snazim se o minimalisticke reseni. Mas jednoduchy addon, co potrebuje zaregistrovat extension metodu? Neni potreba delat dalsi novou tridu, staci poznamka v composer.json.
Pořád mi to připadá jako overkill, navíc limitující. Spíš než snažit se podchytávat každou možnost (extension method, …), umožnil bych modulárnost.
V praxi:
Je potřeba extension method ⇒ vytvořit interface IBeforeStartup a pokud
uživatel chce, zakomponuje volání na tenhle interface do své aplikace
(třeba vytvořením vlastní Application třídy). Pokud ne, zavolá extension
method teprve až ji potřebuje.
Jde mi o to předejít magičnosti, abych se nemusel divit proč to funguje, ale abych věděl, proč to nefunguje a co s tím.
Editoval echo (2. 8. 2012 15:32)
- juzna.cz
- Člen | 248
@echo, @Juan a dalsi zastanci Symfony/Kdyby way – zkuste udelat proof of concept: vezmete treba 10 addonu a zkuste z nich udelat addony dle vasi predstavy. Pro zaklad uz je udelany Pull Request, ze ktereho muzete vychazet. Udelejte upraveny sandbox, do ktereho bude mozne addony jednoduse pridavat.
At si to ozkousite, jak dobre/spatne se to pouziva. Navic ostatni a hlavne ja budeme mit konkretni ukazky a bude se daleko lepe diskutovat, nez jen spekulovat.
- LeonardoCA
- Člen | 296
echo: zatim chapu composer tak, ze nainstaluje vsechny potrebne balicky v takovych verzich aby byly spolu kompatibilni. Jak to dokazes se svym resenim? Mam pocit, ze to co pises resi neco uplne jineho nez resi composer.
To ze juzna resi pridani assets do layoutu je uplne samostatna vec, kterou nekdo nemusi vubec vyuzit, ale zaklad si myslim je, aby se stahly korektni verze balicku. Kdyz nekdo bude mit projekt postaveny na jQuery 1.4 a prida si addon vyuzivajici nejnovejsi verze, tak mu addon nepojede a bude se divit proc. A composer by mel pred tim varovat. To je v zakladu vse.
Jde mi o reseni zavislosti uz behem instalace!
Editoval LeonardoCA (2. 8. 2012 16:16)
- echo
- Člen | 134
LeonardoCA napsal(a):
echo: zatim chapu composer tak, ze nainstaluje vsechny potrebne balicky v takovych verzich aby byly spolu kompatibilni. Jak to dokazes se svym resenim? Mam pocit, ze to co pises resi neco uplne jineho nez resi composer.
Nerozumíme si. Common assety řeším tak, že z nich vytvořím composer balíček s patřičnou verzí a pak na ně odkážu mým způsobem.
Je to trochu prasárna, ale práci to odvede a pro mě je to přehledné.
- Filip Procházka
- Moderator | 4668
Ukážu vám další řešení, které už funkční a používám ho ;)
Už jsem pákrát psal, že používám assetic. Udělal jsem si nad ním základní nádstavbu, aby kamarádil s Nette.
Tohle funguje v pohodě, takže jsem to rozšířil a udělal nad tím nepovinnou nádstavbu v podobě balíčků. Balíčky se definují do souboru úplně stejně jako se definují závislosti v composeru. Chtěl jsem aby to vypadalo co možná nejvíce podobně.
A díky HeaderControl, které mi propojuje nádstavbu nad Asseticem s Presenterem a šablonami, můžu takto snadno vložit do stránky libovolné „balíčky“ (a pořád funguje i starý způsob)
<!DOCTYPE html>
<html>
{head title => "Nette Application Skeleton"}
<meta name="description" content="Nette Framework web application skeleton">
<link rel="shortcut icon" href="{$basePath}/favicon.ico" type="image/x-icon">
{assets jquery/ui, nette/forms, nette/ajax}
{/head}
Je to alfa verze, takže neřeší verze a umí jenom základní věci.
- Jan Jakeš
- Člen | 177
Tak jsem si to trochu pročetl a hlavní problém juznova řešení vidím v tom, že ohýbá composer na něco, k čemu prostě není. Composer by měl každý addon nahrát, vyřešit jeho verzi a závislosti a tím by to mělo (podle mě) pro Composer končit. Kdo nechce/nemůže používat Composer, stáhne addon a někam ho nakopíruje.
Pokud má assety něco někam kopírovat/zpracovávat/cacheovat, měl by to být buď přímo framework anebo nějaký addon, který budou ostatní addony (které potřebují pracovat s assety) vyžadovat (např. nějaký AsseticAddon).
Můj návrh assety přímo zatím neřeší, ale řešil jsem tam to, že lze zjistit složku každého addonu, čímž by se dalo dostat k adresáři s assety. Způsob, jakým je vytahovat, jsem schválně zatím nijak neřešil, protože někdo chce Assetic někdo WebLoader a někdo nic.
Myšlenka @echo s IAssets
se mi libí.
Mít u addonu nějakou metodu, která by vrátila pole jeho assetů je podle
mě ideální. To, jak s nimi pak naložíme už je další stupeň problému a
opravdu toto může řešit třeba i sám nějaký addon.
Souhlasím s juznou, že by možná nebylo nutné, aby můj návrh addonů vytvářel
všechny metody pro události aplikace, atd. a že by si je addon mohl
registrovat sám. Ale musí to být jednoduše a jasně proveditelné.
Aby každý neprasil ve svém addonu své vlastní hacky. Navíc lze u mého
řešení zavést konvence ve stylu „pokud jsou assety ve složce
assets, nemusím dělat nic, aby je framework našel, pokud ne,
přepíšu si nějakou metodu getAssets“. Ale jak říkám, ten
IAssets
zní taky jako dobrý nápad.
Stojím si za tím, že Addon má být prostě předně nějaká
třída (ať už poděděná nebo s interface), která nabídne základní
věci jako přístup k případným assetům, Presenterům a dalším složkám
addonu. Instalace je podle mě to, že připíšu jeden řádek do bootsrap
anebo (lépe) do nějakého assets.neon
. To, jak se addon dostane
do mého projektu (např. Composerem anebo nakopírováním) by s jeho
instalací/registrací podle mě nemělo nijak souviset!
Jinak souhlas s juznou, chtělo by to předvést více kódu a addonů v praxi. Teď se k tomu bohužel nedostanu. Pokud to bude aktuální, tak až se v září vrátím do civilizace, můžu se pokusit rozvinout svůj pull o řešení routování a předvést nějaké addony.
Editoval Juan (2. 8. 2012 18:23)
- Jan Jakeš
- Člen | 177
Ad overkill – prave naopak, snazim se o minimalisticke reseni. Mas jednoduchy addon, co potrebuje zaregistrovat extension metodu? Neni potreba delat dalsi novou tridu, staci poznamka v composer.json.
Tohle je asi zásadní věc, na které se neshodneme. Podle mě toto prostě nemá v Composeru aboslutně co dělat.
Editoval Juan (2. 8. 2012 18:26)
- hrach
- Člen | 1838
Tak jsem si to trochu pročetl a hlavní problém juznova řešení vidím v tom, že ohýbá composer na něco, k čemu prostě není. Composer by měl každý addon nahrát, vyřešit jeho verzi a závislosti a tím by to mělo (podle mě) pro Composer končit. Kdo nechce/nemůže používat Composer, stáhne addon a někam ho nakopíruje.
Pokud má assety něco někam kopírovat/zpracovávat/cacheovat, měl by to být buď přímo framework anebo nějaký addon, který budou ostatní addony (které potřebují pracovat s assety) vyžadovat (např. nějaký AsseticAddon).
Můj návrh assety přímo zatím neřeší, ale řešil jsem tam to, že lze zjistit složku každého addonu, čímž by se dalo dostat k adresáři s assety. Způsob, jakým je vytahovat, jsem schválně zatím nijak neřešil, protože někdo chce Assetic někdo WebLoader a někdo nic.
Myšlenka @echo s IAssets se mi libí. Mít u addonu nějakou metodu, která by vrátila pole jeho assetů je podle mě ideální. To, jak s nimi pak naložíme už je další stupeň problému a opravdu toto může řešit třeba i sám nějaký addon.
toto presne podepisuji :)
- juzna.cz
- Člen | 248
Nerikam, ze s vami nesouhlasim, ale:
Juan napsal(a):
… hlavní problém juznova řešení vidím v tom, že ohýbá composer na něco, k čemu prostě není.
Dle Composer manualu pro custom-installery: At times it may be necessary for a package to require additional actions during installation…
Pokud má assety něco někam kopírovat/zpracovávat/cacheovat…
Dle manualu: …such as installing packages outside of the default vendor library.
… Podle mě toto prostě nemá v Composeru aboslutně co dělat.
Dle manualu pro sekci extra: Arbitrary extra data for consumption by scripts.
Stojím si za tím, že Addon má být prostě předně nějaká třída…
Proc to musi byt trida? Proc ne radeji deklarativni zapis pomoci
json/neon, jak navrhuji napr. ja, HopsaLan
nebo Chrome v declarativeWebRequest
rozsireni (a mnoho dalsich). Nemusi to byt vubec v composer.json
,
klidne to muzeme zapsat do addon.neon
. Duvody, proc se mi vice libi
deklarativni zapis, jsem tu jiz psal.
Proc tedy radeji Addon trida nez addon.neon?
- echo
- Člen | 134
@juzna
Jestli se bude používat třída, nebo neon je jedno. Hlavní je, aby to neměl
na starosti composer. Ten pouze stáhne, uloží záznam o addonu do kontejneru
(neon, db, json) a vygeneruje neon pro user nastavení (extension name).
Dále:
- Potřebujeme přidat do DI → jednoduché, kdo by používal něco jiného než Nette\DI\Container? ⇒ řešením upravit Nette\Application\Application, aby projel kontejner a podle nastavení v neonu přidal rozšíření.
- Interakce mezi službami v DI → pokud umožníme změnu extension name, musí se použít autowiring.
- Potřebujeme assety → složitější, ne každý používá Webloader, Assetic. v šablonách se musí registrovat něco dřív, něco později ⇒ poskytnout službu registrovanou v NetteExtension, která po zavolání např. $addonManager->getAssets(‚Echo511/Plupload‘) vrátí pole s js, css, obrázky.
- Řešíme obrázky → zapeklité, třeba nakopírovat do WWW_DIR, ale strukturu interního asset adresáře si každý vývojář volí svou a css odkazující na obrázky používají právě tuto strukturu ⇒ použití filtru na css (nepraktické, svazující), nebo konvence adresářové struktury (svazující, ale přehledné) HLASUJU ZDE, nebo nechat na uživateli.
Zapomněl jsem na něco mimo ty čtyři body?
Zítra se pustím do Proof of concept.
- Jan Jakeš
- Člen | 177
Dle Composer „manualu“…
Abych to upřesnil – já si myslím, že prostě instalaci assetů, přidávání CompilerExtensions a další podobné věci nemá řešit žádný nástroj typu Composer. Tzn. je mi celkem jedno, co mají v manuálu, protože „z pohledu ze strany Nette“ toto podle mě prostě není správně. (Asi máš pravdu, že „z pohledu Composeru“ jsou tyto akce v pořádku.)
Proc to musi byt trida? Proc ne radeji deklarativni zapis pomoci json/neon, jak navrhuji napr. ja, HopsaLan nebo Chrome v declarativeWebRequest rozsireni (a mnoho dalsich). Nemusi to byt vubec v
composer.json
, klidne to muzeme zapsat doaddon.neon
. Duvody, proc se mi vice libi deklarativni zapis, jsem tu jiz psal. Proc tedy radeji Addon trida nez addon.neon?
Třída je, pro mě, asi tou nejčistší cestou v PHP. Nemusím řešit žádnou adresářovou strukturu, žádné cesty ke konfiguračním souborům (resp. ty samozřejmě můžu mít a přístup k nim poskytne právě tato třída), atd., jediné, co potřebuji je, že mi třídu načte nějaký loader. Při instalaci addonu zmíním do nějakého addons.neon pouze tuto třídu a je vystaráno.
Nejsem ale úplně proti tomu zápisu, co navrhuješ. Jen si moc nedokážu
představit instalaci addonu. Jak by to vypadalo? Jak to řešit elegantně,
čistě a jednotně? Pokud chci, aby mi Composer addon pouze uložil kamsi do
hloubky vendor
adresáře (a jak už jsem řekl, stojím si za
tím, aby zde Composer více neřešil), jak se dostanu k tomu
addon.neon
, tedy nějak elegantně? Jak přidám/registruju tento
addon do mé aplikace? Jestli mám uvádět celou cestu, k
addon.neon
, tak to je přesně to, co nechci. Naopak pouze uvést
třídu je podle mě velmi čisté, elegantní a jednotné. A to, že by někdy
ta jedna třída byla třeba prázdná, to mě opravdu netrápí.
(Btw. to kam odkazuješ na HosipLana, to je pouze zápis assetů pomocí JSON, ale rozhodně to není žádný deklarativní zápis addonů. Kdyby používá Packages, které jsou reprezentovány také třídami.)
Editoval Juan (3. 8. 2012 11:00)
- juzna.cz
- Člen | 248
@Juan Presvecil jsi me. Rucne si vlozit do
config.neon
tridu addonu a nechat composer nebo jakykoliv jiny
autoloading mechanismus, aby si ji nasel, je spravne reseni.
Jak se k tomu zase dostanu, zkusim ty ukazkovy addony udelat v nove branch
timto zpusobem.
Trosku me to vsak porad mrzi, protoze takto nepujde udelat plna automatizace, jak jsem si predstavoval.
Mel jsem takovou krasnou utopickou ideu, ze by addony mohly mit i nejaky
wizzard (jako ma ted composer init
). Pri instalaci by se tak
zeptaly uzivatele: „hele, potrebuju nastylovat, chces nahrat defaultni
styly?“ a kdyz by to uzivatel potvrdil, tak by se css-ko nakopirovalo (nebo
pridalo do webloaderu).
Nebo by se addon zeptal „hele, jsem v zakladu anglicky, ale umim i cestinu a nemcinu, jak mluvis ty?“ a prihodil by i jazykovou mutaci.
A tak, mno. Ale je pravda, ze uz i s odstupem jen par dni se mi to zacina libit min a min.
- Jan Jakeš
- Člen | 177
To jsem rád, že se nakonec vcelku shodnem :)
Chápu kam si tím mířil, ta plná automatizace je lákavá, ale správné/čisté se mi to nezdá. Pokud se teď shodnem na tom, že by se addon registroval jedním řádkem (uvedením jeho třídy) kdesi v configu, addons.neon nebo bootstrapu, můžem přemýšlet, co dál. Podle mě by stejně měla jít většina věcí zautomatizovat. Místo procesu instalace a otázky na jazykovou mutaci by se tato mutace dala nastavit např. v configu, atd.
Teď mě ale zajímá tvůj názor na další postup. Líbí se ti víc nějaká dědičnost (viz můj pull request) anebo použití více interfaců jako to navrhoval echo? Každé má své výhody, dědičnost je asi jednodušší vyřešit/naimplementovat a velice snadno lze nechávat třídu addonu téměř prázdnou, protože nadřazená třída Addon by měla základní implementace všech metod. Interfacy by byly víc psaní, více kódu, ale zase asi poměrně elegantní cesta. Co si o tom myslíš?
Editoval Juan (4. 8. 2012 11:44)
- juzna.cz
- Člen | 248
Juan napsal(a):
… ta plná automatizace je lákavá, ale správné/čisté se mi to nezdá.
Teď mě napadlo ultimátní řešení kombinujicí vše. Splníme tím jak (a) instalaci pomocí jedné třídy, nikomu nic nenucení a nekopírování, tak také (b) možnou plnou automatizaci, pokud bude chtěna.
Způsob: Addon bude mít uvedeno jako type nette-addon, ale už nebude vyžadovat addon-installer (ten bude pouze třeba v suggest). To je pro úplně běžné zacházení v pořádku. Vše bude fungovat, tak jako to zastává Juan.
Pokud bude chtít uživatel plnou automatizaci, tak mu ji můžeme přidat jako třešničku na dortu. V takovém případě si přidá do svého projektu (root composer.json) závislost na addon-installeru, který najednou začne instalovat addony se vší parádou.
Do composer.json, sekce extra se pouze uvede třída zastřešující Addon (tak jako je to např u custom-installerů; aby si ji mohl addon-installer dohledat, když bude použit).
jazykova mutace by se dala dala nastavit např. v configu
Sypu si popel na hlavu. Proč mě toto nenapadlo??? Tak to má být.
V případě ultimátní kombinace se installer může na jazyk zeptat a do configu ho přidat. Ale to je zatím daleká budoucnost… Zatím neřešme.
dědičnost anebo použití více interfaců
Raději interfaces – je to univerzální a nikomu nevnucuješ, od koho má dědit. Ale k tomu i defaultní BaseAddon třída s obecnou implementací, aby se nemuselo hodně kódu opakovat.
- redhead
- Člen | 1313
Raději interfaces – je to univerzální a nikomu nevnucuješ, od koho má dědit. Ale k tomu i defaultní BaseAddon třída s obecnou implementací, aby se nemuselo hodně kódu opakovat.
Tohle jsem chtěl napsat a pak jsem na to zapomněl. Ty dvě věci se přeci nevylučují, spíš naopak a běžnou praxí je interface, který je realizován nějakou abstraktní base třídou pro pohodlnost.
Jinak palec nahoru. Jsem zvědav, kam to dotáhnete, zní to všechno jak rajská hudba ;)
- Jan Jakeš
- Člen | 177
Pravda pravda. A super nápad od juzny – tedy, že napřed uděláme řešení, které nebude souviset s Composer custom-installery a pak Composer tuto instalaci kdyžtak naučíme. To se mi líbí.
Má první otázka tedy zní – co potřebujeme za interfaces? Napadá mě: možnost routování na presentery addonu, možnost vrácení nějakého pole assetů, možnost registrace CompilerExtension, možnost registrace callbacků do životního cyklu aplikace. Toto je podle mě základ, který by snad měl pokrýt potřeby většiny addonů, další kdyžtak vyplynou až se pokusíme addony do této podoby přepsat. Zapomněl jsem na něco?
Ještě k assetům: Myslím, že je to opravdu největší problém, co se týče nějaké automatizace, univerzálního řešení atd. Líbí se mi juznovy nápady ohledně nějakých speciálních typů addonů pro např. JS knihovny. Tedy např. jQuery by byl addon implementující pouze nějaké IAssets. Obrovskou výhodu zde vidím v tom, že by verze i těchto JS knihoven dokázal takto vyřešit Composer. Navíc by toto mohl naprosto zautomatizovat web addonů – tedy sám by nabízel z GitHubu všechny verze např. jQuery a přidával k nim composer.json s příslušnou verzí a tu obalující třídu.
Pokud pak budeme tvořit nějaký addon, který by všechny assety includoval sám, objeví se další problém – assety musí být načteny ve správném pořadí. Jenže toto pořadí (tedy který addon závisí na kterém) půjde vyčíst jedině z composer.json. (Což by asi nevadilo, protože i když někdo nepoužívá Composer, composer.json by u addonu byl.)
- Jan Jakeš
- Člen | 177
Ještě jedno zamyšlení. Je otázka, co by měl řešit nějaký interface a na co stačí CompilerExtension. Například přidávání callbacků do životního cyklu aplikace lze řešit přes CompilerExtension:
$container->getDefinition('application')
->addSetup('$service->onStartup[] = ?;', array(array('@service', 'method')));
Jenže tento zápis není vůbec hezký. Ovšem, kdyby se vylepšila syntax
tohoto zápisu anebo se alespoň přidaly nějaké metody typu
registerOnStartup()
, tak by tento zápis mohl být dostačující a
interface by na toto nemuselo být potřeba. Sám se tedy asi přikláním
k tomu, neřešit callbacky application v nějakém BaseAddon
a
nedělat na to interface, protože to prostě přes CompilerExtension jde a
třeba to v budoucnu půjde i elegantněji.
Některé frameworky navíc využívají kontejner ještě v širším smyslu a mají v něm téměř vše. Pokud se dobře pamatuju, tak myslím, že např. v Kdyby se do něj registrují i Presentery a přidává se jim nějaký tag. Při routování se pak Presentery hledají právě v kontejneru. To už je ale trochu o filozofii frameworku – tedy co řešit přes kontejner a co ne.
- Filip Procházka
- Moderator | 4668
Já bych to nekomplikoval :)
interface Addon
{
function compile($configurator, $compiler);
}
interface AddonAppEvents
{
function listen($application);
}
interface AddonAssets
{
function listAssets();
}
class MyAddon extends Nette\Object implements Addon, AddonAppEvents, AddonAssets
{
public function compile($configurator, $compiler)
{
$compiler->addExtension('doctrine', new DI\DoctrineExtension);
}
public function listen($app)
{
$app->onError[] = $this->appError;
}
public function appError($app, $e)
{
MyLogger::log($e); // třeba
}
public function listAssets()
{
return Nette\Utils\Finder::files('*')->from(__DIR__ . '/Resources/public');
}
}
- repli2dev
- Člen | 57
Juan napsal(a):
Vůbec nechápu, co řešíš. Composer naprosto dostatečně zvládá řešit závislosti mezi balíčky. Pokud mám balíček, který vyžaduje jiný balíček, Composer to vyřeší.
No naprosto nezvládá… když do toho zatáhneš repozitáře. https://github.com/…faqs/why-can't-composer-load-repositories-recursively.md
A zrovna pro vývoj neustále balíčkovat mi přijde jako overkill, z tohoto hlediska se mi zdá Composer neštastným a pro mě tento účel (dle mě) nevhodným.
- Filip Procházka
- Moderator | 4668
@repli2dev: Tak jdi, vyřeš to a pošli
pullrequest, když jsi takový odborník ;) Ok, tak jinak.
Tohle (jak je vidět z jejich rozboru) řešit nejde (cc @hrach). Protože když dovolíš definovat repozitáře jinde než v rootu, brzy narazíš na nezanedbatelnou pravděpodobnost konfliktu. Řekl bych, že zrovna tahle feature je naprosto zanedbatelná. Definovat repozitáře stačí v rootu. A stačí ti na to jeden, nějaký společný pro Nette Addony, který bude zašťiťován Nette webem.
Oni chápou repozitář jako zdroj balíčků, verzovaný repozitáře je něco jiného. Proč by se z těchto nedaly udělat „klasické“ balíčky a importovat je do systému (do addons portálu)? Pak nebudeš vlastní repozitář (pro svůj virtuální balíček) potřebovat.
A pokud potřebuješ vnitrofiremní věci, tak ti zase stačí definovat repozitář v rootu. Tohle opravdu není problém.
Editoval HosipLan (7. 8. 2012 11:40)
- Jan Jakeš
- Člen | 177
juzna.cz napsal(a):
Rekl bych, ze toto je spatna otazka. Spravna otazka je: 1/ na jaka mista se navazuji stavajici addony; 2/ ze kterych z nich udelat interfaces a jake?
To je pravda, ale měli bysme vytvořit nějaký základní pull a podle něj pak zkusit přepsat addony. Tzn. jen pár základních interfaces, které tam budou na 100%. A řekl bych, že jsou to ty tři az čtyři interfaces, které jsme tu vyjmenovali.
Já zítra odjíždím daleko mimo civilizaci a zpět budu někdy v půlce září, tak pokud budete s addony pokračovat, hodně zdaru a těším se, v jakém stavu je najdu v září :) Pak kdyžtak rád s něčím pomůžu.