Nette – pohled začátečníka (splní má očekávání?)

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Ondřej Mirtes
Člen | 1536
+
0
-

Dobře, takže jediný „problém“ je s Texy. Pokaždé, když odevzdám novou zakázku s mým CMS, ve kterém bude Texy zabudované, odvedu ti licenční poplatek. Kolem takovéto 16. zakázky (16 * 490 Kč + DPH = cca 9750 Kč) už dostanu multilicenci, kterou budu moci používat neomezeně.
A v případě, že budu CMS s Texy aplikovat na nějaký vlastní projekt (který nikomu „neodevzdávám“), nemusím platit nic. Je to tak? :)

romansklenar
Člen | 655
+
0
-

Já chápu multilicenci tak, že si o ní musíš zažádat a že i na 20 jednotlivě zakoupených licencí se vztahuje jednotná cena 490,– + dph, pokud koupíš najednou 10 a více máš 40% slevu.

Takže dle mého koupí 16ti jednotlivých licencí multilicenci nezískáš, pokud tedy víš že se nad těch 16 zakázek dostaneš, vyplatíce se ti ji koupit už teď.

PS: Pokud se Davide pletu, oprav mě, samotného mě zajímá jak to je.

David Grudl
Nette Core | 8142
+
0
-

Všechno je věcí dohody :-)

Ondřej Mirtes
Člen | 1536
+
0
-

Tak to se omlouvám, já myslel, že jsem četl o té automatické platnosti multilicence i při postupném zakupování jednotlivých licencí. Asi to bylo jinde :)
Až to bude aktuální, tak se s tebou dohodnu, díky :)

Mám opět pár dotazů ohledně práce s Nette:

  • @layout.phtml nějaký svůj vlastní presenter? Potřebuji do něj nějak dostat data, např. title tag, klíčová slova pro jednotlivá views a spousta dat do obsahu, který je v každém view – obvykle nějaké menu či postranní sloupec, ve kterém generuji dynamický obsah.
  • Jak pro nějaký presenter-view udělám výjimku, že se nemá zobrazovat v kontextu @layout.phtml? Např. RSS zdroj či sitemap pro Google. Celý web chci mít zkrátka tak, aby se zobrazoval jako content->render() v @layout.phtml, ale pro nějaké stránky potřebuji výjimku…

Díky.

David Grudl
Nette Core | 8142
+
0
-

Změnu layoutu zajistí $this->setLayout('jinysoubor') nebo úplné vypnutí $this->setLayout(FALSE), kde tím $this je myšlen presenter. Proměnné, které se vloží do $this->template->promenna = 'hodnota', jsou pak dostupné jak v layoutu, tak v šabloně view.

Ondřej Mirtes
Člen | 1536
+
0
-

Geniální :) Je myšleno opravdu na vše.

Ještě jeden na dobrou noc (okruh toho, co jsem kdy v čistém PHP potřeboval řešit, se pomalu, ale jistě zužuje): Potřebuji na webu provést akci, ke které ale nebude přiřazené žádné view, po správném provedení se provede někam redirect (např. přidání komentáře – mám stránku s článkem, napíšu komentář, odešlu ho formulářem nějakému skriptu, ten ho přidá do DB a pošle prohlížeč zpátky na stránku s článkem). Jak toto provést v Nette? Určitě nějak AJAXově, ten jsem ale zatím ještě nezkoumal. Kdybych na něj nepomyslel, asi bych vytvořil AddCommentPresenter, v nějaké z metod jeho životního cyklu bych přidal komentář a „sprostě“ pomocí HttpResponse provedl přesměrování. Tuším, že to není asi ideální řešení, ale zároveň mě nenapadá lepší.

na1k
Člen | 288
+
0
-

LastHunter napsal(a):

Geniální :) Je myšleno opravdu na vše.

Potřebuji na webu provést akci, ke které ale nebude přiřazené žádné view, po správném provedení se provede někam redirect

Já jsem tohle řešil pomocí signálů (funkce handle{Signal}) – je to krásně jednoduché a dá se to i zAJAXit. Většinou funkci končím rozhodnutím, zda byl požadavek přes JS nebo GET a podle toho buď přesměruju nebo spouštím nějakou JS odezvu. (Jestli je to správný postup nevím, mně to tak funguje :-) )

Jod
Člen | 701
+
0
-

Pozri sa v dokumentácii na snippety. Ja osobne používam toto.

Ondřej Mirtes
Člen | 1536
+
0
-

Díky. Další dotázky:

  • Mám komponentě přiřazovat také její model? A může být u ní nebo ho mám přesouvat také do složky models? Je mi jasné, že může být kdekoli, ale jde mi o co „nejlepší“ best-practice. Jestli mám mít ArticleControl.php v /controls/ArticleControl/ a a ArticleControlModel.php v /models/ArticleControl/…
  • Jak vyřešit odkazy na úrovni jednotlivých textů v databázi? Jde mi o to, když už mám zprovozněný web a píšu v něm články a chci ve svém článku odkázat někam dovnitř webu. V editoru/Texyle zadám pevný link, tím ale podkopu systém dynamicky se vytvářejících odkazů. Když pak přidám nějaké persistentně přenášený parametr, ve všech odkazech v aplikaci se sice automaticky přidá, ale ve všech článcích ho budu muset upravovat ručně…
_Martin_
Generous Backer | 679
+
0
-

LastHunter napsal(a):

  • Jak vyřešit odkazy na úrovni jednotlivých textů v databázi? Jde mi o to, když už mám zprovozněný web a píšu v něm články a chci ve svém článku odkázat někam dovnitř webu. V editoru/Texyle zadám pevný link, tím ale podkopu systém dynamicky se vytvářejících odkazů. Když pak přidám nějaké persistentně přenášený parametr, ve všech odkazech v aplikaci se sice automaticky přidá, ale ve všech článcích ho budu muset upravovat ručně…

Podobná otázka se tu už kdysi řešila, moje odpověď zní následovně.

Ondřej Mirtes
Člen | 1536
+
0
-

Tak jsem se do toho už pustil :)

Vytvořil jsem si komponentu ShortNews, která má za úkol zobrazovat poslední aktuality v pravém sloupci na stránce a v případě nakliknutí archivu pak i výpis novinek po měsících.

Postřehy:

  • Hodil by se mi nějaký BaseControl, abych v dalších komponentách opisovat vytvoření šablony (Control bohužel nedědí od Presenteru, takže nemá metody beforeRender aj. kam bych to mohl nacpat), registraci filtrů, helperů apod. A nejlépe, pokud by se registrace filterů a helperů shodovala s tím, co mám v BasePresenteru, abych opravdu nic nemusel psát/měnit dvakrát. Máte nějaký nápad, jak toho docílit?
  • Filter date z továrny jsem si musel nahradit vlastním, který použije funkci date, protože strftime nepodporuje zobrazení měsíce bez počáteční nuly, takže se pro mě stal nepoužitelným (10. 2. vypadá lépe než 10. 02.). Nebo jsem něco přehlédl?
  • V jakém formátu dibi doporučuje ukládat čas článků? Já jsem zvyklý na unix timestamp, takže to v dibi musím házate jako %i (integer), což mi nepřijde zrovna přirozené.

Váhám, jestli zde pastovat teď ze začátku některé zdrojáky, abyste mi řekli, jestli to dělám špatně/dobře, ale tak aspoň ukážu model:

/**
 * ShortNews Control's model
 */
class ShortNewsModel {

    public static function getFirstNews()
    {

        $news = dibi::query("SELECT time, text from [:pre:shortnews]
                            where del=0 and time<=%i",time(),"
                            order by time desc
                            limit 0,%i",Environment::getConfig("count")->news);

        return $news;
    }

}

Zde jsem chtěl předávat jako konstruktor název tabulky, ve které má hledat, ale přišlo mi pak neobratné dibi posílat ten název tabulky jako parametr (cca takhle: "[:pre:%s",$this->tableName,"]", takže jsem to nechal takto.
Šel by ten model napsat nějak lépe/dělá se to jinak? :)

Teď jdu studovat Ajax a snippety :))

Díky.

Editoval LastHunter (10. 2. 2009 15:55)

Etch
Člen | 403
+
0
-

LastHunter napsal(a):

Zde jsem chtěl předávat jako konstruktor název tabulky, ve které má hledat, ale přišlo mi pak neobratné dibi posílat ten název tabulky jako parametr (cca takhle: "[:pre:%s",$this->tableName,"]", takže jsem to nechal takto.

To by mělo jít zapsat myslím i jednodušeji například takto :

dibi::query("SELECT * FROM %n", ':pre:'.$this->tableName);
David Grudl
Nette Core | 8142
+
0
-

LastHunter napsal(a):

  • Hodil by se mi nějaký BaseControl, abych v dalších komponentách opisovat vytvoření šablony (Control bohužel nedědí od Presenteru, takže nemá metody beforeRender aj. kam bych to mohl nacpat), registraci filtrů, helperů apod. A nejlépe, pokud by se registrace filterů a helperů shodovala s tím, co mám v BasePresenteru, abych opravdu nic nemusel psát/měnit dvakrát. Máte nějaký nápad, jak toho docílit?

O novou šablonu lze požádat přímo presenter ($this->presenter->createTemplate()), ale vzniká tak nadstandardní závislost mezi komponentou a presenterem a komponenta nebude znovupoužitelná.

Pro registraci filtrů přímo v komponentě doporučuji přepsat createTemplate, jako to dělá BasePresenter v příkladu skeleton.

  • Filter date z továrny jsem si musel nahradit vlastním, který použije funkci date, protože strftime nepodporuje zobrazení měsíce bez počáteční nuly, takže se pro mě stal nepoužitelným (10. 2. vypadá lépe než 10. 02.). Nebo jsem něco přehlédl?

Na strftime tu padlo už více stížností, asi to nahradím za date. Jen nevím, jak to udělat zpětně kompatibilně.

  • V jakém formátu dibi doporučuje ukládat čas článků? Já jsem zvyklý na unix timestamp, takže to v dibi musím házate jako %i (integer), což mi nepřijde zrovna přirozené.

dibi je to fuk, ukládej jak chceš.

Váhám, jestli zde pastovat teď ze začátku některé zdrojáky, abyste mi řekli, jestli to dělám špatně/dobře, ale tak aspoň ukážu model:

Je to v pohodě, jen taková obecná rada: statické metody jsou zlo :-)

Ondřej Mirtes
Člen | 1536
+
0
-

David:
strftime – když se ve $format detekuje znak %, použít strftime, jinak date? :) Jen takový nástřel, takhle bych to řešil já-prase :)
unix timestamp – tak jinak, jaký formát doporučuješ ty? :)
statické metody – na to už jsem před chvílí přišel, byla to taková oprátka. Už jsem to nahradil za klasické OOP. Počet SQL dotazů byl totiž nepříjemně vysoký, takhle je to vše jen jednou, jak má být :)

Ondřej Mirtes
Člen | 1536
+
0
-

Uff, tak mám první problém.

Definoval jsem následující routy:

$router[] = new Route('index.php', array(
    'presenter' => 'Default',
    'view' => 'default',
), Route::ONE_WAY);

$router[] = new Route('/', array(
    'presenter' => 'Default',
    'view' => 'default',
));

$router[] = new Route('/archiv-anket', array(
    'presenter' => 'PollsArchive',
    'view' => 'default',
));

.htaccess:

php_flag magic_quotes_gpc off
php_flag register_globals off

RewriteBase /

# front controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.(pdf|js|ico|gif|jpg|png|css|rar|zip|tar\.gz)$ index.php [L]

Odkazy se mi podle toho v aplikaci vytvoří správně, tedy ten jeden odkaz na PollsArchive: . Ale když na něj klepnu, tak server mi předhodí Error 404. Myslím, že se to k Nette ani nedostane. Dělá mi to i na localhostu i na webhostingu.

Jiné (neNette) weby mi na localhostu fungují, ale tam mám v .htaccess vypsanou každou cestu (podobně jak to teď budu vypisovat v routách místo do .htaccess), takže jí to najde.

BTW: Mám presentery pojmenovávat podle toho, jakou chci cestu, která k nim pak vede? Ušetřil bych v definicích rout, ale možná bych v tom nadělal zmatky.
BTW2: Když chci, aby stránku Nette našlo i v případě, že je na konci cesty lomítko (preferuji tvary bez lomítka), mám ke každé variantě připsat ještě ONE_WAY verzi s lomítkem? Nebo to jde nějak úsporněji?

Jod
Člen | 701
+
0
-

No mám pocit že máš buď chybu v htaccess, alebo si vypni v bootstrap errorPresener a catchErrors.

BTW1: Pomenovávaj si ich ako ti ako programátorovi najlepšie vyhovuje a všetko si nastavíš podľa požiadaviek v routach na konci. To PoolsArchive sa mi zdá fajn.
BTW2: Ja keď dám link s lomítkom na konci tak mi presmeruje na ten istý bez lomítka, tak tam nevidím problém.

Ondřej Mirtes
Člen | 1536
+
0
-

.htaccess jsem sem postnul, v něm chybu nevidím (dokonce má i správný název souboru :)). Mod_rewrite taky funguje. Ukážu ještě index.php a bootstrap.php:

<?php

// absolute filesystem path to the web root
define('WWW_DIR', dirname(__FILE__));

// absolute filesystem path to the application root
define('APP_DIR', WWW_DIR . '/../app');

// absolute filesystem path to the libraries
define('LIBS_DIR', WWW_DIR . '/../libs');

// absolute filesystem path to the libraries
define('MODELS_DIR', APP_DIR . '/models');

// relative filesystem path (for hypertext link) to the phpBB3 forum
define('FORUM_DIR', '/forum');

// load bootstrap file
require APP_DIR . '/bootstrap.php';

?>
<?php

require_once LIBS_DIR . '/Nette/loader.php';

if (substr_count($_SERVER["HTTP_HOST"],"alanwake.cz") > 0)
{
    Environment::setMode('production');
}

Environment::loadConfig(APP_DIR."/config.ini");

Debug::enable();

$autoload = new RobotLoader();
$autoload->addDirectory(LIBS_DIR);
$autoload->addDirectory(APP_DIR);
$autoload->register();

$application = Environment::getApplication();

require_once(dirname(__FILE__) . '/routers.php');

$application->run();

?>

K názvům těch presenterů – musím to ještě rozmyslet. Správnými (českými) názvy, tak, jak je chci v URL, bych ušetřil hodně v definicích těch rout…

UPDATE: Já jsem vůl :D V tom .htaccess mi chybělo RewriteEngine On :D

Editoval LastHunter (12. 2. 2009 20:39)

stpnkcrk
Generous Backer | 189
+
0
-

K těm názvům – už jsi se díval na překladový slovník pro route?

Ondřej Mirtes
Člen | 1536
+
0
-

skocourek: To je přesně to, co jsem hledal :)

Musím říct, že jsem se při výběru Nette opravdu nezmýlil. Konečně mám v aplikaci lepší pořádek a hlavně mě dostala přeměna komponent na ajaxové pár řádky kódu :) A když se objeví nějaký problém, vždycky přispěchá Nette s nějakým elegantním řešením.

Sice mívám problém sem tam něco rozchodit, je to přeci jen práce v „cizejším“ prostředí, než když pracuji v čistém PHP, ale to se časem naučím :) A jestli píšu komponenty znovupoužitelné, to se dozvím až ve druhém projektu :o)

Jod
Člen | 701
+
0
-

Vidíš, väčšinou je chyba v nejakej blbosti =)))

A jestli píšu komponenty znovupoužitelné, to se dozvím až ve druhém projektu :o)

Môžem potvrdiť ;)

Nette by som nemenil

kravčo
Člen | 721
+
0
-

LastHunter napsal(a):

$router[] = new Route('/archiv-anket', array(
    'presenter' => 'PollsArchive',
    'view' => 'default',
));

Nemôže byť problém v lomke na začiatku?

Ondřej Mirtes
Člen | 1536
+
0
-

kravco napsal(a):

LastHunter napsal(a):

$router[] = new Route('/archiv-anket', array(
    'presenter' => 'PollsArchive',
    'view' => 'default',
));

Nemôže byť problém v lomke na začiatku?

Nene, bylo to v tom, že se mi z .htaccess nějak vytratil RewriteEngine on ;)

Ondřej Mirtes
Člen | 1536
+
0
-

Nikde jsem nenašel, jestli se dá ovlivnit podoba URL, pokud na ni vede signál nějaké komponenty. Např. budu mít výpis nějakého archivu článků, co když ho zpracuji celý jako komponentu? (tzn. nebude to presenter volaný s různými parametry view, ale komponenta, jejíž vykreslený obsah se bude ovlivňovat signálem).
Řeším takhle archiv článků – mám ho, tedy budu mít v Ajaxu, nahoře lišta s výběrem měsíců, po nakliknutí měsíce se bez znovunačtení stránky zobrazí články z jiného měsíce. V šabloně ArticleArchive:default je jen kód {?$articleArchive->renderArchive()}.

Nevím, jak v routách ovlivnit tvar té URL, na které se ten výsledek bude zobrazovat a také nevím, jak to podstrčit vyhledávači (možná skrytými odkazy na jednotlivé měsíce?), když na ty podstránky vede cesta přes nakliknutí měsíce v selectboxu (viz ten link v minulém odstavci).

Navrhnul jsem to celé blbě nebo se to dá nějak vyřešit? :)

EDIT: Když nad tím tak přemýšlím, měl bych se jako vývojář vždy rozhodovat, zda poslat data presenteru jako argument view (parametru funkce renderView) anebo jako signál presenteru či komponentě. Jak to rozlišit a kdy co použít? Signál je méně praktický – router nejspíš neumožňuje upravit tvar URL, který vede na presenter ovlivněný signálem a je tak horší pro SEO…

Doufám, že mě z toho někdo rozmotáte :)

Editoval LastHunter (14. 2. 2009 0:51)

Ondřej Mirtes
Člen | 1536
+
0
-

Achjo, Nette mě přestává mít rádo. Nikde jsem nenašel, jak by se měly ošetřovat neexistující stránky. Nakonec jsem to z několika threadů tady na fóru poslepoval:

	public function actionArticle($seo) {
		//handling non-existing article etc.

	$model = new MiscArticleModel("misc");

	if (!$model->articleExists($seo))
		{
		throw new BadRequestException("Page not found", 404);
		}
	}
class ErrorPresenter extends BasePresenter {

   public function actionDefault($exception)
        {
            if ($exception instanceof /*Nette\Application\*/BadRequestException) {
                Environment::getHttpResponse()->setCode(404);
                $this->template->title = '404 Not Found';
                $this->setView('404');
            } else
            {
                Environment::getHttpResponse()->setCode(500);
                $this->template->title = '500 Internal Server Error';
                $this->setView('500');

                /*Nette\*/Debug::processException($exception);
             }
          }

  public function render404() {

  }
}

Problém je, že v takovém případě se to na ErrorPresenter vůbec nedostane. Laděnka je vypnutá pomocí catchExceptions = TRUE, ale vše, co se mi dostává, je jen apacheovská stránka „404 Not Found – The requested URL was not found on this server.“

_Martin_
Generous Backer | 679
+
0
-

To není Apacheovská hláška, to je hláška Nette v okamžiku, kdy dojde k chybě a není nastaven ErrorPresenter. Máš v bootstrapu kromě $application->catchExceptions = TRUE; nastavené i $application->errorPresenter = 'Error';?

Ondřej Mirtes
Člen | 1536
+
0
-

Uff, díky, zafungovalo. Já měl zato, že ta hodnota Error v té proměnné je už nastavená jako defaultní…

_Martin_
Generous Backer | 679
+
0
-

Původně byla, ale to už je dávná historie (naposledy v revizi 41).

Ondřej Mirtes
Člen | 1536
+
0
-

Už se mi to podařilo zprovoznit, ale mám problém, že se mi ty komponenty překreslují, i když nevolám invalidaci. (Jedna komponenta se mi vykresluje do více podob, renderArchive na daném view a renderFewNews na každé stránce vpravo). Pokud zavolám handleMonth (který ovlivňuje pouze archiv), který invaliduje pouze archiv, zinvaliduje se mi i ta část vpravo. Koukal jsem, co posílá JSON a jsou tam napsány fakt oboje. Když oboje (!) invalidace zakomentuju, stále to funguje :/

K nahlédnutí zde: http://beta.alanwake.cz/kratke-zpravy

public function handlePage($page)
{
    $this->page = $page;
    //$this->invalidateControl("news");
}

public function handleMonth()
{
    $this->month = $this->months[$_POST["month"]];
    //$this->invalidateControl("archivenews");
}

public function renderFewNews() {

    $template = parent::createMyTemplate(dirname(__FILE__) . '/' . 'FewNews' . '.phtml');

    //filling variables
    $newsModel = new ShortNewsModel();
    $template->news = $newsModel->getFewNews($this->page);
    $template->page = $newsModel->getPaginator()->page;
    $template->nextPage = $newsModel->getPaginator()->page+1;
    $template->previousPage = $newsModel->getPaginator()->page-1;
    $template->isFirst = $newsModel->getPaginator()->isFirst();
    $template->isLast = $newsModel->getPaginator()->isLast();

    $template->render();

}

public function renderArchive() {

    $template = parent::createMyTemplate(dirname(__FILE__) . '/' . 'Archive' . '.phtml');

    $newsModel = new ShortNewsModel();

    $monthinator = new Monthinator($this->month);

    $template->news = $newsModel->getNewsByMonth($monthinator->getStart(), $monthinator->getEnd());
    $template->render();

}
Jod
Člen | 701
+
0
-

Pozri či sa ti control neinvaliduje sám. $this->invalidateControl(false);

Ondřej Mirtes
Člen | 1536
+
0
-

Jod napsal(a):

Pozri či sa ti control neinvaliduje sám. $this->invalidateControl(false);

ee, to nic neudělá :( I když tohle zavolám v konstruktoru, stále se to přepisuje.

BTW: Zavolání:

$this->validateControl();
$this->invalidateControl("news");

už je lepší, ale nevím, proč je Control defaultně celý zinvalidněný.

Editoval LastHunter (16. 2. 2009 15:06)

Jod
Člen | 701
+
0
-

A neinvaliduješ ten control ešte niekde inde? Alebo neinvaliduješ nadradený/parent Presenter/Control?

Vyzerá to akoby sa ti po nejakom kliku invalidovala celá stránka. Nemáš nič také v presenteru?

Inak ten design sa mi páči, tvoja práca? =)

Editoval Jod (16. 2. 2009 15:08)

Ondřej Mirtes
Člen | 1536
+
0
-

Jod napsal(a):

A neinvaliduješ ten control ešte niekde inde? Alebo neinvaliduješ nadradený/parent Presenter/Control?

Vyzerá to akoby sa ti po nejakom kliku invalidovala celá stránka. Nemáš nič také v presenteru?

Inak ten design sa mi páči, tvoja práca? =)

Ee, nic takového nedělám. Ale je to vyřešené zavolám validateControl(), jen by mě zajímalo, proč je jako defaultně nastavený celý invalidateControl();
Design – „můj“ grafik, se kterým na tom webu spolupracuji :)

Jod
Člen | 701
+
0
-

No controly/presentery sa mi zdá, že sa pri nejakej akcii invalidujú, ale momentálne mi nevie prísť na um kedy to je :D

LM
Člen | 206
+
0
-

Control se sám automaticky invaliduje pokud obdrží signál.

Editoval LM (16. 2. 2009 16:12)

Ondřej Mirtes
Člen | 1536
+
0
-

LM: A k čemu je pak volání invalidateControl(„snippet“), když už je celý invalidovaný?

Mám dotaz: Umí Nette už nějakou simulaci jmenných prostorů? Rád bych odlišil webovou prezentaci a administrační rozhraní a zároveň to měl v jedné struktuře app/root/libs. Omlouvám se, že mám takto základní otázky, ale nepodařilo se mi o tom najít článek/zmínku…

Honza Marek
Člen | 1664
+
0
-

Mám dotaz: Umí Nette už nějakou simulaci jmenných prostorů? Rád bych odlišil webovou prezentaci a administrační rozhraní a zároveň to měl v jedné struktuře app/root/libs.

Jo, řiká se tomu moduly.

Jod
Člen | 701
+
0
-

Moduly si môžeš omrknúť v nette examples.

LM
Člen | 206
+
0
-

LastHunter napsal(a):

LM: A k čemu je pak volání invalidateControl(„snippet“), když už je celý invalidovaný?

Tak můžeš invalidovat i jinou komponentu ne jen tu která obstarává signál nebo snippet presenteru.

Ondřej Mirtes
Člen | 1536
+
0
-

Díky.

Zkopíruju sem příspěvek z minulé stránky, protože se na něj jaksi pozapomnělo a pro mě má dost zásadní význam. Takže díky za odpovědi :)

Nikde jsem nenašel, jestli se dá ovlivnit podoba URL, pokud na ni vede signál nějaké komponenty. Např. budu mít výpis nějakého archivu článků, co když ho zpracuji celý jako komponentu? (tzn. nebude to presenter volaný s různými parametry view, ale komponenta, jejíž vykreslený obsah se bude ovlivňovat signálem). Řeším takhle archiv článků – mám ho v Ajaxu, nahoře lišta s výběrem měsíců, po nakliknutí měsíce se bez znovunačtení stránky zobrazí články z jiného měsíce. V šabloně >ArticleArchive:default je jen kód {?$articleArchive->renderArchive()}.

Nevím, jak v routách ovlivnit tvar té URL, na které se ten výsledek bude zobrazovat a také nevím, jak to podstrčit vyhledávači (možná skrytými odkazy na jednotlivé měsíce?), když na ty podstránky vede cesta přes nakliknutí měsíce v selectboxu (viz ten link v minulém odstavci).

Navrhnul jsem to celé blbě nebo se to dá nějak vyřešit? :)

EDIT: Když nad tím tak přemýšlím, měl bych se jako vývojář vždy rozhodovat, zda poslat data presenteru jako argument view (parametru funkce renderView) anebo jako signál presenteru či komponentě. Jak to rozlišit a kdy co použít? Signál je méně praktický – router nejspíš neumožňuje upravit tvar URL, který vede na presenter ovlivněný signálem, neumožňuje mi zakázat přístup na něj pro roboty (např. hlasování v anketě) a je tak horší pro SEO…