custom url router working also in test mode
- pn-pm
- Member | 20
basically i want to place dynamic urls from posts like /post1-url or even leveled (containing slash) /post2/with/slash-url to router, to be matched against database, and either display content if available, or use next router rule.
I feel there should be a way using $router->match() + routeList if not matched, but did not find out how
So far i fave came up w fn placed in ErrorPresenter startup:
// ErrorPresenter
function startup(){
$httpRequest = $this->getHttpRequest();
if(DbPost::exists($httpRequest)){
$this->forward('Home:viewDbPost', $httpRequest )
}
}
How can i continue in testing, with Tracy bar on, debug mode to true?
If i put the debugMode to true, I end up in red error page from
nette,
and if not, i dont have Tracy bar available.
Possible workaround is, set debug mode in the vieDbPost construct fn again by
some cookie, but is it ok?
Second issue is, if done like this, the response also has response code
404, which i dont know how and where to change
Maybe there is some better approach to match dynamic urls?
btw, is there presenterExists() and presenterActionExists() ?
maybe i could direct all urls to one action, and forward, but need to know if
presenter and action does match other router rules
Last edited by pn-pm (2023-07-18 14:43)
- m.brecher
- Generous Backer | 872
@pn-pm
How can i continue in testing, with Tracy bar on, debug mode to true?
If i put the debugMode to true, I end up in red error page from nette,
and if not, i dont have Tracy bar available.
If you want to test real rendering of error page you should set debugMode to true + use special configuration in common.neon file:
application:
catchExceptions: true
You will have Tracy bar + real error pages
Last edited by m.brecher (2023-07-18 17:38)
- m.brecher
- Generous Backer | 872
@pn-pm
Maybe there is some better approach to match dynamic urls?
I dont know what exactly mapping url ⇒ database content you want to do. But I had in the past one similar case, where I placed in the same url parameter articles + article categories. In controller I tried first select from database the category and if not exists than select the article. In php this is very simple. In Nette Router unnecessarily complicated. Simply get the parameter from url, pass it to the presenter and in presenter solve matching the right content from the database.
- pn-pm
- Member | 20
got it working! info from @m.brecher helped (thank you), in finall state its done like this
application:
catchExceptions: true
then in ErrorPresenter i changed the response presenter in BadRequesException:
if ($exception instanceof Nette\Application\BadRequestException) {
[$module, , $sep] = Nette\Application\Helpers::splitName($request->getPresenterName());
//BEFORE: return new Responses\ForwardResponse($request->setPresenterName($module . $sep . 'Error4xx'));
return new Responses\ForwardResponse($request->setPresenterName($module . $sep . 'Home'));
}
and finally, in HomePresenter, i have actionDefault to check if article with URL exists
public actionDefault(){
$httpRequest = $this->getHttpRequest();
$slug = substr($httpRequest->url->path,1);
$page = $this->Posts->getByUrl($slug);
$httpResponse = $this->getHttpResponse();
if(!empty($page)){
$httpResponse->setCode(Nette\Http\Response::S200_OK);
$this->template->pageContent = $page;
$this->changeAction('viewPage'); // tpl specific for posts
} else {
$this->template->pageContent = false; // in template then display 404 msg based on this
$httpResponse->setCode(Nette\Http\Response::S404_NotFound);
}
}
One funny thing though, if i test article url /abcd/efgh, TracyBar displays router info to be matching Abcd:efgh but im really in the HomePresenter, where the ErrorPresenter redirected me :D (reason is, last Router Route i have is a classic ‘<presenter>/action’) and is matched, even if such presenter does not exist… any way to fix this?
Btw: is there a way to list all registered Presenters ? like
$this->getPresenters();
Last edited by pn-pm (2023-07-19 12:04)
- jeremy
- Member | 54
I'd just simply create a route that automatically sends you to your Home presenter with any URI.
$router->addRoute('<permalink .+>/', [
'presenter' => 'Home',
'action' => 'default',
'permalink' => ''
]);
Leave the Error presenter the way it was before and instead pass
actionDefault the permalink parameter.
Then check if the page exists and if not, use $this->error() to send a
404 response.
This is just an example:
public function actionDefault(string $permalink): void {
$post = $this->Posts->getByUrl($permalink);
if (empty($post)) {
$this->error();
}
Rest of your code...
}