router bez presenteru, pouze www.example.cz/produkt

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

už delší dobu si lámu hlavu, jak docílit toho, abych url nemusela obsahovat název presenteru
chtěl bych mít adresu například www.example.cz/produkt, ale i www.example.cz/výrobce

takto to má například megapixel: http://www.megapixel.cz/

jediné co mne napadlo je, že si vytvořit v databázi tabulku, která by obsahovala všechna url a k nim by byl přiřazen presenter

existuje nějaké lepší řešení? :-)

nanuqcz
Člen | 822
+
0
-

Ahoj, jediné řešení bude asi napsat si vlastní router. Předat mu připojení k databázi a pak se vždy ptát (přímo v routeru):

  1. Existuje takový výrobce, jaký je napsaný v URL? ⇒ Vrať Request pro akci „Manufactorers:default“
  2. Existuje takový produkt, jaký je napsaný v URL? ⇒ Vrať Request pro akci „Product:show“

Napsal bych i ukázkový kód, ale vlastní router jsem nikdy nepsal, tak bych v tom určitě udělal nějakou botu :-)

Editoval xxxObiWan (23. 11. 2011 17:59)

Paradiso
Člen | 101
+
0
-

to bude asi nejlepší řešení, s tím, že bych si udělal tu tabulku kde budou všechny url, aby byly unikátní, například:

CREATE TABLE `url` (
    `id` int(11) NOT NULL,
    `url` varchar(255) NOT NULL,
    `presenter` varchar(50) NOT NULL,
    `action` varchar(50) NOT NULL,
  UNIQUE KEY `url` (`url`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

id by byla idčka produktů,výrobců,…
url by bylo unikátní
presenter a action asi bez komentáře

router by si vybral podle url z db id, presenter a akci a dal request

už mi jen chybí ten příklad, jak správně v routeru udělat request:-)

tak kdyby někdo věděl, tak bych byl rád :-)

Editoval Paradiso (23. 11. 2011 18:45)

nanuqcz
Člen | 822
+
0
-

No, podle API to vypadá jednoduše

$url = dibi::fetch("SELECT * FROM `url` WHERE ...");
return new \Nette\Application\Request($url['presenter'], $url['action'], $this->getParam());

…ale neručím za to :-) Vyzkoušej a pak řekni.

Paradiso
Člen | 101
+
0
-

díky, už jsem se koukal také do dokumentace, zítra to vyzkouším zprovoznit a dám vědět:-)

Paradiso
Člen | 101
+
0
-

tak jsem si zkusil vytvořit vlastní routu, ale laděnka my vyhazuje
No route for Front:Default:default(url=5)
v debugbaru mám:
yes MyRoute Default:default url = 5

a kód routy vypadá takto: (zatím tam v podstatě nic není, pouze jsem chtěl otestovat, pokud bych si vkládal do $presenter vlastní hodnotu, zda by to šlo:-)

class MyRoute extends Nette\Object implements Application\IRouter
{

	public function __construct()
	{

	}


	public function match(Nette\Http\IRequest $httpRequest)
	{
            //\Nette\Diagnostics\Debugger::dump($httpRequest);
                $presenter = 'Default';
                $params = array('url'=>5);

		return new Application\Request(
			$presenter,
			$httpRequest->getMethod(),
			$params,
			$httpRequest->getPost(),
			$httpRequest->getFiles()
		);
	}


	public function constructUrl(Application\Request $appRequest, Nette\Http\Url $refUrl)
	{

	}

}

jsem v oop začátečník, tak mne nekamenujte za nějakou blbost pls:-)

voda
Člen | 561
+
0
-

Nette provádí https://doc.nette.org/…tion/routing#…, takže se pokouší vytvářit pro Request url, ale protože to nemáš naimplementováno, tak ti to selže. Kanonizaci url můžeš tedy dočasně zakázat.

Paradiso
Člen | 101
+
0
-

Tak vlastní routa je hotova, funguje, tak jak jsem si přál.
(pokud máte návrhy, co zlepšit, budu jen rád, přeci jen s nette teprve začínám:-))

zde je kód, třeba někdo využije:-)

<?php

namespace Plugins;

use Nette,
	Nette\Application;

/**
 * @author     Jan Matoušek
 */
class MyRoute extends Nette\Object implements Application\IRouter
{

    private $database;

	public function __construct(Nette\Database\Connection $database)
	{
                $this->database = $database;
	}


	public function match(Nette\Http\IRequest $httpRequest)
	{
		$url = $httpRequest->getUrl();
                $ParamUrl = explode($url->scriptPath,$url -> path);

                $result = MyRouteModel::transformUrl($this->database, $ParamUrl[1]);

                $params = array();

                if($result){
                    $params['urlid'] = $result->url_id;
                    $params['id'] = $result->id;
                    $params['action'] = $result->action ?: 'default';
                    $params += $httpRequest->getQuery();

                    $presenter = $result->presenter;
                } elseif(empty($ParamUrl[1])){
                    $presenter = 'Default';
                } else {
                    throw new Nette\Application\BadRequestException;
                }
                    return new Application\Request(
                            $presenter,
                            $httpRequest->getMethod(),
                            $params,
                            $httpRequest->getPost(),
                            $httpRequest->getFiles()
                    );
	}


	public function constructUrl(Application\Request $appRequest, Nette\Http\Url $refUrl)
	{
		$params = $appRequest->getParams();

                $query = $params;
                unset($query['urlid'], $query['id'], $query['action']);

                if(isset($params['urlid'])){
                    $urlId = $params['urlid'];

                    $result = MyRouteModel::transformBackUrl($this->database, $urlId);
                    $ParamUrl = $result->url;
                } else {
                    $ParamUrl = '';
                }

                if(count($query)>0){

                    $queryString = '?';

                    foreach($query as $key=>$parameter){
                        $queryString .= $key.'='.$parameter.'&';
                    }

                    $finalQueryString = substr($queryString,0,-1);

                    $url = $refUrl->getScheme().'://'.$refUrl->getHost().$refUrl->getPath().$ParamUrl.$finalQueryString;

                } else {
                    $url = $refUrl->getScheme().'://'.$refUrl->getHost().$refUrl->getPath().$ParamUrl;
                }

               return $url;
	}

}

Editoval Paradiso (27. 11. 2011 12:32)

Paradiso
Člen | 101
+
0
-

A ještě mám jeden zádrhel. Na localhostu vše ok, ale pokud to spustím na hostingu, tak mi to stále hází 404, ale jen šablonu. Hlavička je 200 a z presenteru, na který přesměrovávám, jdou vypsat dumpem hodnoty, takže opravdu je načtený, ale nezobrazuje se mi šablona, čím by to mohlo být?

Editoval Paradiso (27. 11. 2011 12:08)

Paradiso
Člen | 101
+
0
-

tak chyba nalezena, akce musí být default *a ne * Default (v přiloženém kódu opravena)

Editoval Paradiso (27. 11. 2011 16:27)