formulář a routy

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

Zdravím. Snažím se vytvořit routu pro detail produktu.
Url by měla vypadat takto: http://shop.cz/…/sporak-bily.
Na stránce je formulář s objednáním produktu.
Pokud použiju SimpleRouter a do action formuláře přidám category a product, tak vše funguje jak má.

<?php

$router[] = new SimpleRouter(array(
        'presenter' => 'Default',
        'action' => 'default',
));

$form->setAction($form->getAction() . '&category='.$categoryUrl.'&product='.$productUrl);

?>

Nedaří se mi ale zprovoznit formulář s pěknými url. Vždycky v action formuláře dostanu No route for Default:detail(do=buy-submit).

<?php
$router[] = new Route('<category>/<product>', array(
	'presenter' => 'Default',
	'action' => 'detail'
));
?>

Stejně je to i se signály. Pokud na detailu produktu použiju handleNeco, tak to zahlásí, že neexistuje routa. Proč se to nedá za otazník http://shop.cz/…/sporak-bily?do=.. jako vždy? Co dělám špatně?

Díky za jakoukoli radu.

php 5.3.0
nette 0.9.2

redhead
Člen | 1313
+
0
-

měl bys to dělat přes metodu link:

$form->setAction($this->link("Presenter:action", $categoryUrl, $productUrl));
//nebo parametry jmenovitě
$form->setAction($this->link("Presenter:action", array('category' => $categoryUrl, 'product' => $productUrl));

Editoval redhead (29. 12. 2009 14:26)

Ondřej Mirtes
Člen | 1536
+
0
-

Já si myslím, že bys to měl dělat jinak. Tohle není podle MVC. Čeho chceš dosáhnout? :) Přesměrování na výsledek bys měl nejspíš provádět v submitovací metodě formuláře, kde už to jde nějak hezky (přes $this->redirect()).

A v routách ti nejspíš chybí taková ta obecná:

$router[] = new Route('<presenter>/<action>', array(
        'presenter' => 'Default',
        'action' => 'default',
));
TeeBee87
Člen | 14
+
0
-

Ondřej Mirtes napsal(a):

Já si myslím, že bys to měl dělat jinak. Tohle není podle MVC. Čeho chceš dosáhnout? :) Přesměrování na výsledek bys měl nejspíš provádět v submitovací metodě formuláře, kde už to jde nějak hezky (přes $this->redirect()).

A v routách ti nejspíš chybí taková ta obecná:

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

Kdybych použil tuto routu tak mi nebude fungovat url ve tvaru kategorie/produkt. Chci dosáhnout toho, aby bylo možné odeslat formulář z url: domaci-spotrebice/sporak-bily nejlépe tak, že se za tuto url přidá parametr do – z toho stavu už pak přesměruji zpět třeba pomocí $this->redirect(‚this‘);

TeeBee87
Člen | 14
+
0
-

redhead napsal(a):

měl bys to dělat přes metodu link:

$form->setAction($this->link("Presenter:action", $categoryUrl, $productUrl));
//nebo parametry jmenovitě
$form->setAction($this->link("Presenter:action", array('category' => $categoryUrl, 'product' => $productUrl));

Díky! Tohle mě nenapadlo. Nevíš ještě prosím jak do action formuláře dostat elegantně parametr, aby se tento formulář zpracoval? (?do=addProduct-submit)

Ondřej Mirtes
Člen | 1536
+
0
-

Kouzlo Nette je ale v tom, že by ses o URL neměl starat – nevidíš sám, jak je to kostrbaté?

Pokud tuto routu dáš jako poslední, tak ti nic nepožere a vše bude fungovat, jak má. Možná ale chyba v její absenci není, nevím.

Formuláře jsou myšleny tak, že odeslaný (a validní formulář) ti zpracuje metoda, která je nejčastěji ve stejném Presenteru jako továrnička daného formuláře (aby to bylo pěkně pohromadě). Po úspěšném zpracování formuláře můžeš uživatele poslat, kam chceš, pomocí $this->redirect() která jako parametry přebírá cílový Presenter:action a jejich parametry – stejně jako makro {link} v šablonách.

Předpokládám, že ta cílová adresa stejně závisí na hodnotách, které uživatel ve formuláři odešle, takže je nemůžeš nastavit v továrničce, kam $form->setAction() patří.

TeeBee87
Člen | 14
+
0
-
<?php

$router[] = new Route('kosik', array(
	'presenter' => 'Default',
	'action' => 'basket'
));

$router[] = new Route('<category>/<product>', array(
	'presenter' => 'Default',
	'action' => 'detail'
));
?>

Odkaz na detail produktu dělám takto:

<a href=„{plink Default:detail, ‚category‘ ⇒ $product->categoryUrl, ‚product‘ ⇒ $product->url}“>{$product->name}</a>

Pokud na stránce s košíkem vytvořím formulář má action takovou: kosik?do=buy-submit
Pokud formulář vytvořím na stránce s detailem produktu dostanu: error: No route for Default:detail(do=buy-submit)

Proč? Mám chybu v routách? Pokud na detailu produktu vytovořím url ručně – v RoutingDebuggeru se to matchne dobře.

Tady jsou všechny routy:

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

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

$router[] = new Route('kontakty', array(
	'presenter' => 'Default',
	'action' => 'contact'
));

$router[] = new Route('kosik', array(
	'presenter' => 'Default',
	'action' => 'basket'
));


$router[] = new Route('admin/<action>', array(
	'presenter' => 'Admin',
	'action' => 'default'
));

$router[] = new Route('<category>', array(
	'presenter' => 'Default',
	'action' => 'products'
));

$router[] = new Route('<category>/<product>', array(
	'presenter' => 'Default',
	'action' => 'detail'
));
?>
Ondřej Mirtes
Člen | 1536
+
0
-

Tuhle vymaž:

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

A tuhle dej na konec:

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

Mělo by to začít fungovat líp.

A určitě by tam šly udělat i další optimalizace :) Máš holt spoustu věcí narvaných v DefaultPresenteru.

Editoval Ondřej Mirtes (29. 12. 2009 18:48)

TeeBee87
Člen | 14
+
0
-

Ondřej Mirtes napsal(a):

Tuhle vymaž:

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

A tuhle dej na konec:

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

Mělo by to začít fungovat líp.

A určitě by tam šly udělat i další optimalizace :) Máš holt spoustu věcí narvaných v DefaultPresenteru.

Dík! Jsi profík ;)

dotTwelve
Člen | 167
+
0
-

Mam podobny problem, asi taky bude chybka nekde v routach.
Na vypisu produktu mam formular, pro ktery nenastavuji setAction a defaultne se nastavi: /produkty/show/5?do=orderForm-submit ale potrebuji: produkty/plavani-a-opalovani/bikiny?do=orderForm-submit, nebo jeste lepe produkty/plavani-a-opalovani/bikiny/objednat. Po odeslani stejne presmeruji pomoci $this->redirect('this') takze na te url ani tolik nezalezi.

V sablone odkazuji takto: {plink Products:show, $category => $category->id, $id => $product->id}

Zde je muj kompletni router:

<?php
Route::addStyle('#cs-presenter', 'presenter');
Route::addStyle('#cs-action', 'action');

Route::setStyleProperty('#cs-presenter', Route::FILTER_TABLE, array(
    'uvod-strana' => 'Default',
    'historie' => 'History',
    'prodejny' => 'Shops',
    'kontakt' => 'Contact',
    'produkty' => 'Products'
));

Route::setStyleProperty('#cs-action', Route::FILTER_TABLE, array(
    'hity-sezony' => 'hits'
));

$router[] = new Route('admin/<presenter>/<action>/<id>', array(
    'module'    => 'Admin',
    'presenter' => 'Default',
    'action'    => 'default',
    'id'        => NULL
));

Route::addStyle('#category');
Route::setStyleProperty('#category', Route::FILTER_IN, 'getCategoryId');
Route::setStyleProperty('#category', Route::FILTER_OUT, 'getCategoryName');

function getCategoryId($url) {
    $id = new CategoriesModel;
    return $id->getIdByUrl($url);
}

function getCategoryName($id) {
    $name = new CategoriesModel;
    return $name->getUrlById($id);
}

Route::addStyle('#product');
Route::setStyleProperty('#product', Route::FILTER_IN, 'getProductId');
Route::setStyleProperty('#product', Route::FILTER_OUT, 'getProductName');

function getProductId($url) {
    $id = new ProductsModel;
    return $id->getIdByUrl($url);
}

function getProductName($id) {
    $name = new ProductsModel;
    return $name->getUrlById($id);
}

$router[] = new Route('hity-sezony', array(
    'module'    => 'Front',
    'presenter' => 'Products',
    'action'    => 'hits',
    'category'  => NULL
));

$router[] = new Route('produkty/<category #category>', array(
    'module'    => 'Front',
    'presenter' => 'Products',
    'action'    => 'default',
    'category'  => NULL
));

$router[] = new Route('produkty/<category #category>/<id #product>', array(
    'module'    => 'Front',
    'presenter' => 'Products',
    'action'    => 'show',
    'category'  => NULL,
    'id'        => NULL
));

$router[] = new Route('<presenter #cs-presenter>/<action #cs-action>/<id>', array(
    'module' => 'Front',
    'presenter' => 'Default',
    'action' => 'default',
    'id' => NULL
));

$router[] = new Route('', array(
    'module' => 'Front',
    'presenter' => 'Default',
    'action' => 'default',
    ), Route::ONE_WAY);
?>

Diky za jakekoliv nakopnuti…

Editoval dotTwelve (6. 7. 2010 18:23)

dotTwelve
Člen | 167
+
0
-

Tak jsem se probudil, napadla me takova vec, a ejhle, ono to funguje. V akci mi chybela jedna promenna public function actionShow($id) {}public function actionShow($category, $id) {}.
Tedka uz ma formular dobrou akci.