Routování jednoduchého zobrazovacího webu
- BaruCepa
- Člen | 33
Zdravím, jsem úplný začátečník na Nette a dávám dohromady poměrně
jednoduchý web, který pouze zobrazuje informace uložené v databázi a peru
se s routováním. Předpokládám, že by to nemělo být nic složitého, ale
už jsem poměrně zoufalá a nevím, co mi uniká. Budu vděčná za každou
konstruktivní kritiku, radu, vysvětlení, cokoliv.
Aktuální RouterFactory :
declare(strict_types=1);
namespace App\Router;
use Nette;
use Nette\Application\Routers\RouteList;
use Nette\Application\Routers\Route;
final class RouterFactory
{
use Nette\StaticClass;
public static function createRouter(): RouteList
{
$router = new RouteList;
$router->addRoute('<presenter>/<action>[/<id>]', 'Core:Page:page');
return $router;
}
}
PagePresenter :
<?php
declare(strict_types=1);
namespace App\CoreModule\Presenters;
use App\CoreModule\Model\PageManager;
use App\Presenters\BasePresenter;
class PagePresenter extends BasePresenter
{
private PageManager $pageManager;
public function __construct(PageManager $pageManager)
{
$this->pageManager = $pageManager;
}
public function renderPage(?string $id = NULL)
{
if (!$id)
{
$page = $this->pageManager->getDefaultPage();
}
else if (!($page = $this->pageManager->getPage($id)))
{
$page = $this->pageManager->getPage('404');
}
$this->template->page = $page;
}
}
Id jednotlivých stránek jsou string jako ‚uvod‘, ‚zakladni-informace‘ atd., které bych samozřejmě ráda využila v url. Localhost zobrazí nastavenou úvodní stránku, jakmile však pomocí url chci zobrazit jinou stránku, zobrazí se 404 a to ani ne z Nette:
Url: localhost/uvod
Not Found
The requested URL was not found on this server.
Apache/2.4.57 (Debian) Server at localhost Port 80
Prosím, jakým způsobem nastavit routování?
- jeremy
- Člen | 54
Jestli to dobre chapu, tak parameter id
v routeru je id/url
stranky, napr: zakladni-informace
.
$router->addRoute('<presenter>/<action>[/<id>]', 'Core:Page:page');
S touto route by url vypadadala takhle:
http://localhost/page/page/zakladni-informace
Pokud chces aby url byla http://localhost/zakladni-informace
,
tak bude zapotrebi upravit route:
$router->addRoute('<id .+>', 'Core:Page:page');
Takto budou vsechny url odkazovat na presenter Page
a action
page
. Parameter id
v tomto pripade prijme jakykoliv
string, vcetne lomitek. Url by mohla byt napriklad
http://localhost/url/to/page
: hodnota parameteru id
by
byla url/to/page
.
Pokud nechces aby to prijmalo i lomitka tak staci misto
<id .+>
dat <id>
.
$router->addRoute('<id .+>', 'Core:Page:page', ['id' => 'uvod']);
Takhle bude zakladni hodnota id
= uvod
. Router by
tak mel automaticky presmerovat http://localhost/uvod
na
http://localhost/
.
Predpokladam, ze uvod je hlavni stranka, pokud ne, tak to neni za potrebi.
Editoval jeremy (26. 9. 2023 15:31)
- BaruCepa
- Člen | 33
@jeremy
Děkuji moc za vysvětlení, bohužel ani tak nefunguje. Pokud nastavím route na
$router->addRoute('<id .+>', 'Core:Page:page');
,jak jsi poradil, vyhodí mi Nette chybu 404, No route for HTTP request. U posledního tipu
$router->addRoute('<id .+>', 'Core:Page:page', ['id' => 'uvod']);
mi to Nette shodilo s tím, že třetí parametr musí být typu int, ne array.
Posílám i .htaccess, jestli problém není tam:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^$ www/ [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^www/
RewriteRule ^(.*)$ www/$1
</IfModule>
Ještě mě napadá, používám Docker, může mít toto nějaký vliv?
Editoval BaruCepa (28. 9. 2023 9:43)
- BaruCepa
- Člen | 33
@mystik
Tak pro momentální RouterFactory v tomto provedení:
declare(strict_types=1);
namespace App\Router;
use Nette;
use Nette\Application\Routers\RouteList;
use Nette\Application\Routers\Route;
final class RouterFactory
{
use Nette\StaticClass;
public static function createRouter(): RouteList
{
$router = new RouteList;
$router->addRoute('<id .*>', [
'presenter' => 'Core:Page',
'action' => 'page',
'id' => 'uvod',
]);
return $router;
}
}
zobrazí na localhost úvodní stránku. Pokud však zadám url localhost/uvod, stále se vrací chyba ne z Nette.
Not Found
The requested URL was not found on this server.
Apache/2.4.57 (Debian) Server at localhost Port 80
Tuhle chybu to hodí na cokoliv, co zadám za lomítko, totiž na každé platné id stránky.
- jeremy
- Člen | 54
$router->addRoute('<id .+>', 'Core:Page:page', ['id' => 'uvod']);
Staci to pole dat jako 2 parameter, tak jak to mas ted, tam jsem se spletl.
$router->addRoute('<id .*>', [
'presenter' => 'Core:Page',
'action' => 'page',
'id' => 'uvod',
]);
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^$ www/ [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^www/
RewriteRule ^(.*)$ www/$1
</IfModule>
.htaccess mas mimo www slozku? Myslim ze bude lepsi mit .htaccess primo
v www adresari a na stranku pristupovat z
http://localhost/www/
.
Tak to budes mit prakticky stejny jako kdyz to bude live na hostingu. Na
hostingu je dulezity si nastavit document root aplikace prave na adresar www,
tim se vyhnes potencialnim hrozbam. Viz: Dokumentace
1 a Dokumentace
2 .
V www adresari pak staci mit rewrite pravidla aby to presmerovavalo
requesty, ktere nejsou soubory nebo adresare na index.php.
Muj .htaccess vypada priblizne takhle:
<IfModule mod_autoindex.c>
Options -Indexes
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
# Remove multiple slashes #
RewriteCond %{THE_REQUEST} \s/+(?:.*?)/{2,}(?:[^\s]*)
RewriteCond %{REQUEST_URI} (.*)
RewriteRule .* %1 [R=301,L,NE]
# Remove trailing slash from existing files #
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_URI} ^(.+\.[^/]+)/$
RewriteRule .* %1 [R=301,L]
# Forward any URI to index.php #
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.+\.[^/]+)/(.+)$ index.php [L]
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_URI} !^/\.well-known(?!/(?:.+/)?\..*)
RewriteCond %{REQUEST_URI} /\..*
RewriteRule .* index.php [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule .* index.php [L]
</IfModule>
Pokud nechces pristupovat na stranku z http://localhost/www/
,
tak bude za potrebi si vytvorit VirtualHost a nastavit document root na www
adresar.
Napriklad muzes mit url: http://project.local/
Editoval jeremy (28. 9. 2023 15:37)
- BaruCepa
- Člen | 33
@jeremy @mystik
Tak jsem uvolnila .htaccess mimo a do toho ve složce www doplnila tvůj vzor.
Nic se nezměnilo, localhost zobrazuje úvodní stránku, cokoliv za lomítkem
zobrazí chybovou hlášku ne z Nette. Pár drobných projektů jsem na Nette
už dělala, pravda, podle návodu, ale žádný nedělal takové potíže.
U tohoto poprvé využívám Docker, tak opravdu nevím, jestli toto nemůže
mít vliv. Ty dřívější projekty klasika pomocí Xampp a příkaz v konzoli
pro vytvoření PHP serveru.
- jeremy
- Člen | 54
Jak pise mystik, chce to zkontrolovat mod_rewrite. Taky bych ale jeste zkusil smazat cache v prohlizeci. Nekdy to pomuze, kdyz se delaji zmeny v htaccess. Staci jit do console v prohlizeci, sekce „Network“ a nahore bud na levo nebo na pravo (zalezi na prohlizeci) zaskrtnout „Clear cache“ a restartovat stranku. Za pokus to stoji.
Spis to ale vypada na ten vypnuty mod_rewrite.
- nightfish
- Člen | 519
@BaruCepa Nemohu si pomoct a znovu sem pošlu odkaz na stránku, která popisuje řešení problémů s routováním – https://doc.nette.org/…ubleshooting#…
Bylo by pěkné, kdyby sis našla čas jednotlivé body projít a případně
napsat, co jsi u jednotlivých kroků zjistila. Zároveň by se asi hodilo,
kdybys mohla s aktuálním popisem chování poslat i aktuální: strukturu
projektu na serveru (v Dockeru) – hlavně do jakého adresáři míří
DocumentRoot
, v jakých adresářích máš soubor(y)
.htaccesss
a jaký je jejich obsah.
A na závěr, pokud se zobrazuje chyba 404 z Apache, by se hodil i celý
příslušný řádek z access_logu (který najdeš podle nastavení Docker
image – buď jako soubor v kontejneru, nebo namountovaný „někam mimo
kontejner“ a nebo přesměrovaný na stdout/stderr kontejneru – v takovém
případě bys musela příslušný řádek najít v
docker logs kontejner_s_apachem
).