Routování jednoduchého zobrazovacího webu

BaruCepa
Člen | 33
+
0
-

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í?

nightfish
Člen | 474
+
0
-

@BaruCepa Zkus mrknout na https://doc.nette.org/…ubleshooting#…

m.brecher
Generous Backer | 763
+
0
-

@BaruCepa

Localhost zobrazí nastavenou úvodní stránku

Pošli, jak máš udělaný .htaccess – tam by mohla být chyba

jeremy
Člen | 50
+
0
-

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
+
0
-

@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)

mystik
Člen | 292
+
0
-

Tu 404 ti vyhodi pro jakoukoli URL? Nebo jen pro URL bez path? Je tam pattern .+ tj. neprazdny retezec. Zkus to zmenit na .*

mystik
Člen | 292
+
0
-

Treti parametr je typ route tam pole nedavej. Do druheho parametru predej pole s klici presenter, action a id.

BaruCepa
Člen | 33
+
0
-

@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 | 50
+
0
-
$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)

mystik
Člen | 292
+
0
-

Tak to uz vypada spis na chybu v konfiguraci webserveru (htaccess) . Mate tam v Apache instalovany a zapnuty mod_rewrite? Kam je nastaveny docroot? A kde mate index.php?

BaruCepa
Člen | 33
+
0
-

@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.

mystik
Člen | 292
+
0
-

A mas docker image kde je v Apache zapnuty mod_rewrite?

jeremy
Člen | 50
+
0
-

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 | 474
+
+1
-

@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).

BaruCepa
Člen | 33
+
0
-

Tak chyba nalezena, je to jak psal mystik, v Dockerfile PHP jsem neměla zapnutý mod_rewrite, tedy tento řádek chyběl

RUN a2enmod rewrite

Po doplnění tohoto řádku a rebuildu funguje routování, jak má. Všem moc děkuji za rady, informace i odkazy, zase vím něco víc :)