Dynamicke routovani podle url

turbo80
Člen | 50
+
0
-

Zdravym, potrebuji poradit jak vytvorit dynamicke routocani.

Www.web.neco/krasny-den/
Presenter:clanky
action:show

V db bych mel ulozeno url(krasny-den), presenter(Clanky),action(show)
a podle url by se poznalo jakej presenter ma url zpracovat doufam ze chapete jak to myslim. Vubec nevim cim zacit. Predem dekuji za vsechny rady..

David Matějka
Moderator | 6445
+
+2
-

ahoj, muzes si napsat vlastni router nebo pouzit globalni filtry, kde provedes dotaz a vratis presenter a action v params

Phalanx
Člen | 310
+
0
-

Pokud budeš chtít dynamicky pouze články, tak ti bude stačit tohle:

<?php

	public static function createRouter(
		\CMS_Page $cms_page
	) {

			$pages = $cms_page->getStaticPagesIdentifiers($lang);
			$router[] = new Route('<identifier [a-z0-9_-]+>', array(
				'presenter' => 'Clanky',
				'action' => 'show',
				'identifier' => array(
					Route::FILTER_IN => function($identifier) use($pages) {
						return !empty($pages[$identifier]) ? $pages[$identifier] : NULL;
					}
				),
			));

?>

přičemž $cms_page je model, kde si tahám všechny možné identifikátory a jen zkontroluju, jestli je identifikátor v poli.

Akorát si tím přidáváš do routeru závislost na databázi. Lepší řešení by bylo mít v url blog/<slug>, nechat routu obecně čímž nepotřebuješ přístup k databázi a zkontroluješ jestli slug existuje až v presenteru.

Editoval Phalanx (22. 9. 2018 12:48)

turbo80
Člen | 50
+
0
-

Nebude to jen pro clanky bude tam fotogalerie, apod.. Uz nevim jak na to hraju si stim uz 14 dni a porad nic. Kdyby slo udelat neco.neco/fotgalerie/dovolena-2018 apod neresil bych to fotogalerie by byl presenter dal by to byl slug(id) apod, ale takhle to prave nechci…

MajklNajt
Člen | 470
+
0
-

turbo80 napsal(a):

Nebude to jen pro clanky bude tam fotogalerie, apod.. Uz nevim jak na to hraju si stim uz 14 dni a porad nic. Kdyby slo udelat neco.neco/fotgalerie/dovolena-2018 apod neresil bych to fotogalerie by byl presenter dal by to byl slug(id) apod, ale takhle to prave nechci…

Najlepšie budeš mať napísať si vlastný router https://doc.nette.org/…tion/routing#…, tiež to mám tak poriešné na weboch, kde nechcem byť fixovaný na nejakú pevnú schému URL.

Čiže v match() si z databázy vytiahneš riadok podľa URL a vrátiš Nette\Application\Request

V constructUrl() si zas z databázy vytiahneš riadok podľa presenteru a akcie (príp. ID) a vrátiš string obsahujúci URL

Tu je pre inšpiráciu môj router:

use Nette;
use App\Model\RouteFacade;
use App\Model\Entities\Route;

class MyRouter implements Nette\Application\IRouter
{
    /** @var RouteFacade */
    private $routeFacade;

    /**
     * MyRouter constructor.
     * @param RouteFacade $routeFacade
     */
    public function __construct(RouteFacade $routeFacade)
    {
        $this->routeFacade = $routeFacade;
    }

    /**
     * @param Nette\Http\IRequest $httpRequest
     * @return Nette\Application\Request|null
     */
    public function match(Nette\Http\IRequest $httpRequest)
    {
        $url = $httpRequest->getUrl();
        $basePath = $url->getBasePath();
        if (strncmp($url->getPath(), $basePath, strlen($basePath)) !== 0) {
            return null;
        }
        $path = (string) substr($url->getPath(), strlen($basePath));
        $route = $this->routeFacade->findByUrl($path);
        if($route instanceof Route) {
            $routeParams = $route->getTargetParams();
            $params = ["action" => $route->getAction(), "id" => $route->getTargetId(), "locale" => $route->getLocale() ?: "sk"];
            if($routeParams) $params += $routeParams;
            $params += $httpRequest->getQuery();
            return new Nette\Application\Request(
                $route->getPresenter(),
                $httpRequest->getMethod(),
                $params,
                $httpRequest->getPost(),
                $httpRequest->getFiles(),
                [Nette\Application\Request::SECURED => $httpRequest->isSecured()]
            );
        }
        return null;
    }

    /**
     * @param Nette\Application\Request $appRequest
     * @param Nette\Http\Url $refUrl
     * @return string|null
     */
    public function constructUrl(Nette\Application\Request $appRequest, Nette\Http\Url $refUrl)
    {
        $scheme = $refUrl->getScheme();
        $baseUrl = $scheme."://".$refUrl->getAuthority().$refUrl->getBasePath();
        $presenter = $appRequest->getPresenterName();
        $params = $appRequest->getParameters();
        if(key_exists("action", $params)) {
            $action = $params["action"];
            unset($params["action"]);
        }
        else $action = "default";
        if(key_exists("id", $params)) {
            $id = $params["id"];
            unset($params["id"]);
        }
        else $id = null;
        if(key_exists("locale", $params)) {
            $locale = $params["locale"];
            unset($params["locale"]);
        }
        else $locale = null;
        $route = $this->routeFacade->findByRequest($presenter, $action, $id, $params, $locale);
        if($route instanceof Route) {
            $url = $baseUrl.$route->getUrl();
            $params = $this->filterUsedParams($params, $route->getTargetParams());
            $query = http_build_query($params);
            if($query !== "") {
                $url .= "?".$query;
            }
            return $url;
        }
        return null;
    }

    /**
     * @param array $params
     * @param array|null $used
     * @return array
     */
    private function filterUsedParams(array $params, array $used = null)
    {
        if($used) {
            foreach($used as $key => $param) {
                unset($params[$key]);
            }
        }
        return $params;
    }

}