Routování odkazů Controlu na sebe sama
- eudard
- Člen | 15
Zdravím Nette komunitu, můj dotaz směřuje na routy v rámci komponent…
Vytvořil jsem si komponentu BlogWidget, která se umí
- zobrazovat seznam článků
- zobrazovat detail článku
- zobrazit formulář pro přidání nového článku
Chtěl bych se zeptat:
- dá se nějak nastavit routy v rámci komponent, aby url aplikace nebylo
/?blogWidget-id=3&do=blogWidget-Detail
ale např./blog/titulekclanku-idclanku
? - co si myslíte o tomto řešení, kdy se nepoužívají Presentery, ale je vše v komponentě ?
Kód vypadá následovně:
BlogWidget.php
class BlogWidget extends Control {
public $action = 'default';
function handleAdd() {
$this->action = 'admin';
}
function handleList() {
$this->action = 'default';
}
function handleDetail($id) {
$this->action = 'detail';
$this->template->detail = BlogWidgetModel::getArticleById($id);
}
public function createComponentBlogAdminForm() {
$form = new Form();
$form -> addText('title','Titulek článku');
$form -> addTextarea('text','Text článku');
$form -> addSubmit('send','Vytvoř');
$form -> onSuccess[] = callback($this , 'addItem');
return $form;
}
public function addItem($form) {
$vals = (array)$form->getValues();
BlogWidgetModel::insert($vals);
$this->flashMessage('Aktualita přidána');
$this->redirect('List');
}
function render() {
$this->template->setFile(dirname(__FILE__).'/BlogWidget.latte');
$this->template->action = $this->action;
$this->template->articles = BlogWidgetModel::getNews();
$this->template->render();
}
}
BlogWidget.latte
{if $action=='default'}
{foreach $articles as $a}
<h2><a n:href="Detail,id=>$a->id">{$a->title}</a></h2>
<p>{$a->text}</p>
{sep}<hr>{/sep}
{/foreach}
<a n:href="Add">Přidej novou položku</a>
{/if}
{if $action=='admin'}
{widget blogAdminForm}
{/if}
{if $action=='detail'}
<h2>{$detail->title}</a></h2>
<p>{$detail->text}</p>
{/if}
Díky za každou reakci..
- Filip Procházka
- Moderator | 4668
Mám velkou radost, že na to chceš dělat komponentu, protože to považuju za správný směr :)
Takže několik doporučení:
- mít jednu šablonu pro komponentu a v ní ify je škaredé. Koukni na LookoutControl, když ho podědíš můžeš psát pak „pohledy“ podobně jako v presenteru a ke každému máš šablonu.
- asi bych na tři účely nepsal jednu komponentu, ale tři komponenty
- asi bych komponenty více řídil presenterem, to znamená každé komponentě buď předávat konstruktorem ID článku a model, nebo rovnou článek, získaný v akci
protected function createComponentArticleDetail()
{
$id = $this->getParam('id', NULL);
if ($id === NULL) {
throw new Nette\Application\BadRequestException('Missing article ID');
}
return new ArticleDetail($this->context->articleModel, $id);
}
A nebo takto, což mě zrovna napadlo a dává to docela smysl :)
// presenter
/** @persistent */
public $id; // routa sem dosadí IDčko článku
protected function createComponentArticleDetail()
{
return new ArticleDetail($this->context->articleModel);
}
{control articleDetail $presenter->id}
Komponenta by pak v render přijímala toto $id
, vytáhla si
článek a vykreslila. Router by měl zařídit, že odkaz na neexistující
článek se zahodí dříve, než se dostane požadavek k presenteru.
- eudard
- Člen | 15
HosipLan napsal(a):
- mít jednu šablonu pro komponentu a v ní ify je škaredé. Koukni na LookoutControl, když ho podědíš můžeš psát pak „pohledy“ podobně jako v presenteru a ke každému máš šablonu.
LookoutControl je naprosto geniální!! Připadalo mě, že když používám pro realizaci komponenty, tak se ochuzuju o vymoženosti Presenteru. LookoutControl tohle alespoň z části řeší – díky za tip!
- asi bych na tři účely nepsal jednu komponentu, ale tři komponenty
Předpokládám že máš namysli rozdělit komponentu na tři asi nejak takto:
- blogWidgetDetail.php + šablona
- blogWidgetList.php + šablona
- blogWidgetAdmin.php + šablona
s tím, že v presenteru si pak určím co chci zobrazit.. opět super nakopnutí!
Router by měl zařídit, že odkaz na neexistující článek se zahodí dříve, než se dostane požadavek k presenteru.
To řízení presenterem navrhuješ právě kvůli routeru ? O ten mi totiž právě jde, zatím se v tom tak nějak plácám a nemůžu pořádně navrhnout správně routy.
Teď řeším router pro adresu
http://localhost/?blogWidget-id=1&do=blogWidget-Detail
aby odkazy vypadaly takto http://localhost/article/id
Zatím jsem přišel na to, že řešení bude pravděpodobně něco jako:
$router[] = new Route("article/<blogWidget-id>/<do>", array(
'presenter' => 'Homepage',
'action' => 'default',
'blogWidget-id'=>NULL,
'do'=>NULL
));
Ale není to optimální, routy mě dělají zatím problémy. Musím to ještě pořádně nastudovat a otestovat.
- Filip Procházka
- Moderator | 4668
Mohlo by tě zajímat: https://forum.nette.org/…dnot-pri-mvc
$articleModel = $container->articleModel;
$router[] = new Route('blog/<article>', array(
'presenter' => 'Article',
'action' => 'default',
'articles' = array(
Route::FILTER_IN => function ($article) use ($articleModel) {
// vubec nepotřebuješ čísla a pokud budou mít dva články stejný název,
// ke druhému přidáš na konec dvojku
return $articleModel->findIdByName($article);
// pokud model nic nenajde, měl by vrátit NULL
},
Route::FILTER_OUT
)
));
$router[] = new Route('<presenter>[/<id>]/', array(
'presenter' => 'Homepage',
'action' => 'default'
))
Potom budeš mít presentery ArticlePresenter
, kde budeš
vypisovat článek, ArticlesPresenter
kde bude jejich seznam a
můžeš mít i ArticleEditPresenter
, který bude vyžadovat
přihlášeného uživatele.