Jak na Router aby místo id vrace titulek
- jAkErCZ
- Člen | 322
Zdravím,
Mám routu
$router[] = new Route('[<locale=cs cs|en>/]<action>', [
'presenter' => 'Front:Works',
'action' => [
Route::FILTER_STRICT => true,
Route::FILTER_TABLE => [
// řetězec v URL => akce presenteru
'works' => 'default',
'detail' => 'detail'
]
]
]);
který vrací url ve tvaru: portfolio/web/detail?work_id=1
Ale rád bych aby místo toho ?work_id=1 to vracelo něco jako název-id aby ty url vypadaly prostě lépe.
Díky všem za rady :)
- Kamil Valenta
- Člen | 822
'[<locale=cs cs|en>/]<action>/<slug>'
A dopíšeš si Route::FILTER_IN, která ověří, zda ten slug odpovídá nějakému ID.
- MajklNajt
- Člen | 502
@jAkErCZ skús trošku potrápiť aj svoju hlavu: https://doc.nette.org/…tion/routing#…
- jAkErCZ
- Člen | 322
MajklNajt napsal(a):
@jAkErCZ skús trošku potrápiť aj svoju hlavu: https://doc.nette.org/…tion/routing#…
No díval sem se na hromadu návodů ale nějak to prostě nechápu.
$router[] = new Route('[<locale=cs cs|en>/]<action>/<slug>', [
'presenter' => 'Front:Works',
'action' => [
Route::FILTER_STRICT => true,
Route::FILTER_TABLE => [
// řetězec v URL => akce presenteru
'works' => 'default',
'detail' => 'detail'
]
],
'slug' => [
Route::FILTER_IN => function ($id){
if(is_numeric($id)){
return $id;
}else{
bdump($id);
$page = $this->worksRepository->getWorkBySlug($id);
return $page->id;
}
},
Route::FILTER_OUT => function ($id){
if(!is_numeric($id)){
return $id;
}else{
$page = $this->productFrontRepository->getWorkBySlug($id);
bdump($page);
exit;
return $page->slug;
}
}
]
]);
A model
public function getWorkBySlug (int $work_id)
{
$work = $this->database->table(self::TABLE_NAME)->where(self::COLUMN_ID, $work_id)->fetchPairs($work_id,'title');
return $work;
// Id článku je 2 => url = lesy
// Vrácení předem vytvořené url | titulek článku upravený přez Nette\Utils\Strings::webalize
}
Co teda dělám špatně vycházel jsem z tohoto a toho co mi tu psal kolega. URL
A po pužití tohoto tak url vypadá takto: web/front.works/detail?work_id=1
A nebo ještě ZDE COOL URL ale také to nefunguje.
Editoval jAkErCZ (4. 4. 2020 15:52)
- David Matějka
- Moderator | 6445
v route pracujes s parametrem slug
a dle vseho generujes URL
s parametrem work_id
- jAkErCZ
- Člen | 322
David Matějka napsal(a):
v route pracujes s parametrem
slug
a dle vseho generujes URL s parametremwork_id
No tady je presenter
public function actionDetail($work_id){
$work = $this->worksRepository->getWork($work_id);
if ($work_id){
$this->template->work = $work;
}else{
$this->redirect(':Front:Homepage:');
}
}
Prostě ať vyzkouším vše na co jsem narazil tak to nefunguje prostě chci aby místo toho /detail?work_id=1 vracel /detail/1-Název ale prostě nenapadá mi normální řešení.
- Mysteria
- Člen | 797
Třeba takhle:
URL budeš mít třeba
http://127.0.0.1:8080/homepage/default/slug-two
a v presenteru
budeš mít místo slug-two normálně 2. Jenom si tam teda musíš místo toho
pole dát databázi, ale to už by snad neměl být problém.
final class HomepagePresenter extends Nette\Application\UI\Presenter
{
public function actionDefault(string $slug): void
{
bdump('ID: ' . $slug);
}
}
final class RouterFactory
{
use Nette\StaticClass;
private const TABLE = [
1 => 'slug-one',
2 => 'slug-two',
];
public static function createRouter(): RouteList
{
return (new RouteList())->addRoute(
'<presenter>/<action>[/<slug>]',
[
'presenter' => 'Homepage',
'action' => 'default',
NULL => [
Route::FILTER_IN => static function (array $parameters): array {
$parameters['slug'] = array_search($parameters['slug'], self::TABLE);
return $parameters;
},
Route::FILTER_OUT => static function (array $parameters): array {
$parameters['slug'] = self::TABLE[$parameters['slug']];
return $parameters;
},
],
]
);
}
}
- jAkErCZ
- Člen | 322
Mysteria napsal(a):
Třeba takhle:
URL budeš mít třeba
http://127.0.0.1:8080/homepage/default/slug-two
a v presenteru budeš mít místo slug-two normálně 2. Jenom si tam teda musíš místo toho pole dát databázi, ale to už by snad neměl být problém.final class HomepagePresenter extends Nette\Application\UI\Presenter { public function actionDefault(string $slug): void { bdump('ID: ' . $slug); } }
final class RouterFactory { use Nette\StaticClass; private const TABLE = [ 1 => 'slug-one', 2 => 'slug-two', ]; public static function createRouter(): RouteList { return (new RouteList())->addRoute( '<presenter>/<action>[/<slug>]', [ 'presenter' => 'Homepage', 'action' => 'default', NULL => [ Route::FILTER_IN => static function (array $parameters): array { $parameters['slug'] = array_search($parameters['slug'], self::TABLE); return $parameters; }, Route::FILTER_OUT => static function (array $parameters): array { $parameters['slug'] = self::TABLE[$parameters['slug']]; return $parameters; }, ], ] ); } }
Tak tvá rada funguje dobře ale mám problém s tím že mi to háže Undefined index: slug ale když dám ignorovat chybu jede to kde to mám tedy definovat?
A ještě upravil jsem si to tedy na DB a našel jsem další problém
NULL => [
Route::FILTER_IN => static function (array $parameters): array {
$parameters['slug'] = array_search($parameters['slug'], $this->worksRepository->getWorkBySlug());
return $parameters;
},
Route::FILTER_OUT => static function (array $parameters): array {
$parameters['slug'] = $this->worksRepository->getWorkBySlug()[$parameters['slug']];
return $parameters;
},
]
Chyba:
Using $this when not in object context
A přitom jsem zkusil i trik co psaly u jiných příspěvků a to upravit config
# Nastavení služeb v rámci celé aplikace.
services:
- App\RouterFactory
router: @App\RouterFactory::createRouter()
a nic
Editoval jAkErCZ (4. 4. 2020 20:25)
- Mysteria
- Člen | 797
Přesně tak, dej pryč to static, pak ti to bude fungovat. A to slug
záleží jak to máš pojmenovaný v předpisu routy. Tzn pokud tam máš
třeba
'<presenter>/<action>[/<mujSuperParameter>]'
, tak
tam budeš používat $parameters['mujSuperParameter']
a
v presenteru taky pak
public function actionDefault(string $mujSuperParameter)
.
Plus bys neměl zapomenout na ošetření toho, když ti někdo ručně upraví adresu na nějakou blbost, aby se to chovalo korektně, když ti to nic nenajde v databázi (nějakej default třeba).
- jAkErCZ
- Člen | 322
Mysteria napsal(a):
Přesně tak, dej pryč to static, pak ti to bude fungovat. A to slug záleží jak to máš pojmenovaný v předpisu routy. Tzn pokud tam máš třeba
'<presenter>/<action>[/<mujSuperParameter>]'
, tak tam budeš používat$parameters['mujSuperParameter']
a v presenteru taky pakpublic function actionDefault(string $mujSuperParameter)
.Plus bys neměl zapomenout na ošetření toho, když ti někdo ručně upraví adresu na nějakou blbost, aby se to chovalo korektně, když ti to nic nenajde v databázi (nějakej default třeba).
Ať dám static pryč nebo ne tak stále to hází Using $this when not in object context
řádek
$parameters['slug'] = $this->worksRepository->getWorkBySlug()[$parameters['slug']];
Fakt už nevím co dělám špatně :(
- Kamil Valenta
- Člen | 822
Mysteria napsal(a):
a v presenteru taky pak
public function actionDefault(string $mujSuperParameter)
.
V presenteru už bych používal ID, na které se mi slug v routeru přeloží. „mujSuperParameter“ coby slug může být závislý třeba na jazykové mutaci, ID už bude nezávislé.
Plus bys neměl zapomenout na ošetření toho, když ti někdo ručně upraví adresu na nějakou blbost, aby se to chovalo korektně, když ti to nic nenajde v databázi (nějakej default třeba).
O to se může postarat už ta FILTR IN, když nenajde odpovídající záznam a vrátí null, routa to ani nematchne a pokud to nematchne ani žádná jiná, padne to do 404.
Editoval kamil_v (4. 4. 2020 23:45)
- Kamil Valenta
- Člen | 822
jAkErCZ napsal(a):
Ať dám static pryč nebo ne tak stále to hází Using $this when not in object context
Fakt už nevím co dělám špatně :(
Ukaž zase asi celou routu.
- Marek Bartoš
- Nette Blogger | 1280
Ať dám static pryč nebo ne tak stále to hází Using $this when not in object context
Ve statických funkcích nemůžeš volat $this. Jsi v kontextu třídy, ne objektu. I když smažeš static z anonymní funkce, tak jsi pořád ve statické metodě createRouter(). Tzn. ani jedno nesmí být static, pak ti $this bude fungovat.
- jAkErCZ
- Člen | 322
kamil_v napsal(a):
jAkErCZ napsal(a):
Ať dám static pryč nebo ne tak stále to hází Using $this when not in object context
Fakt už nevím co dělám špatně :(Ukaž zase asi celou routu.
Tady je celý router
class RouterFactory
{
use StaticClass;
/** @var WorksRepository */
public $worksRepository;
public function __construct(WorksRepository $worksRepository)
{
$this->worksRepository = $worksRepository;
}
/**
* Vytváří a vrací seznam routovacích pravidel pro aplikaci.
* @return IRouter výsledný router pro aplikaci
*/
public static function createRouter()
{
$router = new RouteList;
$router[] = new Route('[<locale=cs cs|en>/]kontakt', 'Front:Contact:default');
/* Administrace */
$router[] = new Route('admin/[<locale=cs cs|en>/]<presenter>/<action>[/<id [0-9]+>]', array(
'module' => 'Admin',
'presenter' => 'Home',
'action' => 'default',
'id' => NULL,
));
$router[] = new Route('[<locale=cs cs|en>/]<action>', [
'presenter' => 'Front:User',
'action' => [
Route::FILTER_STRICT => true,
Route::FILTER_TABLE => [
// řetězec v URL => akce presenteru
'profil' => 'default',
'prihlaseni' => 'login',
'odhlasit' => 'logout',
'registrace' => 'register'
]
]
]);
$router[] = new Route('[<locale=cs cs|en>/]<action>[/<slug>]', [
'presenter' => 'Front:Works',
'action' => [
Route::FILTER_STRICT => true,
Route::FILTER_TABLE => [
// řetězec v URL => akce presenteru
'works' => 'default',
'detail' => 'detail'
]
],
NULL => [
Route::FILTER_IN => static function (array $parameters): array {
$parameters['slug'] = array_search($parameters['slug'], $this->worksRepository->getWorkBySlug());
return $parameters;
},
Route::FILTER_OUT => static function (array $parameters): array {
$parameters['slug'] = $this->worksRepository->getWorkBySlug()[$parameters['slug']];
return $parameters;
},
]
]);
$router[] = new Route("[<locale=cs cs|en>/]<presenter>/<action>[/<id>]", "Front:Homepage:default");
return $router;
}
}
a presenter
public function actionDetail(string $slug){
$work = $this->worksRepository->getWork($slug);
if ($slug){
$this->template->work = $work;
}else{
$this->redirect(':Front:Homepage:');
}
}
- MajklNajt
- Člen | 502
nechcem byť zlý, ale
- robíš špatne to, že začínaš od konca, treba doštudovať základy OOP – v statickej triede nemá čo hľadať konštruktor
- treba poriadne čítať, napr. dokumentáciu https://doc.nette.org/…tion/routing#… – Jakékoliv závislosti, třeba na databázi, nebo příznak, lze předat do továrny routeru jako parametry
- jAkErCZ
- Člen | 322
MajklNajt napsal(a):
nechcem byť zlý, ale
- robíš špatne to, že začínaš od konca, treba doštudovať základy OOP – v statickej triede nemá čo hľadať konštruktor
- treba poriadne čítať, napr. dokumentáciu https://doc.nette.org/…tion/routing#… – Jakékoliv závislosti, třeba na databázi, nebo příznak, lze předat do továrny routeru jako parametry
Chápu :)
NULL => [
Route::FILTER_IN => static function (array $parameters) use ($worksRepository): array {
$parameters['id'] = array_search($parameters['id'], $worksRepository->getWorkBySlug());
return $parameters;
},
Route::FILTER_OUT => static function (array $parameters) use ($worksRepository): array {
bdump($worksRepository->getWorkBySlug());
$parameters['id'] = $worksRepository->getWorkBySlug()[$parameters['id']];
return $parameters;
},
]
Do modelu už se to normálně napojí a vytáhne ale háže mi to stále
Undefined index: id
$parameters['id'] = $worksRepository->getWorkBySlug()[$parameters['id']];
A ještě mě napadlo jak využiju webalize když Model mám takto
public function getWorkBySlug ()
{
return $this->database->table(self::TABLE_NAME)->fetchPairs('work_id','title');
}
Díky za radu
- David Matějka
- Moderator | 6445
a proc zas pracujes s parametrem id
, kdyz pred tim bylo videt,
ze mas v definici routy slug
? pak se nediv, ze index neexistuje.
prijde mi, ze vubec nevis, co se deje, a snazis se to vyresit nahodnyma upravama
kodu. projdi si v klidu dokumentaci, pohledej na foru, kde se to hodnekrat
resilo, koukni na nejaky videa z poslednich sobot, kde se routování
probíralo…
a vytahnout si z databaze vsechny prispevky, abys zjistil, kde slug
odpovida, je velmi neefektivni. udelej si v databazi
sloupecek slug
- jAkErCZ
- Člen | 322
David Matějka napsal(a):
a proc zas pracujes s parametrem
id
, kdyz pred tim bylo videt, ze mas v definici routyslug
? pak se nediv, ze index neexistuje. prijde mi, ze vubec nevis, co se deje, a snazis se to vyresit nahodnyma upravama kodu. projdi si v klidu dokumentaci, pohledej na foru, kde se to hodnekrat resilo, koukni na nejaky videa z poslednich sobot, kde se routování probíralo…a vytahnout si z databaze vsechny prispevky, abys zjistil, kde slug odpovida, je velmi neefektivni. udelej si v databazi sloupecek
slug
Ale já reaguju na to co si psal ty… to znamená že já sem pracoval s $work_id tudíž vše jsem předalal na $work_id tak jak mám v db.
Viz
Router:
$router[] = new Route('[<locale=cs cs|en>/]<action>[/<work_id>]', [
'presenter' => 'Front:Works',
'action' => [
Route::FILTER_STRICT => true,
Route::FILTER_TABLE => [
// řetězec v URL => akce presenteru
'works' => 'default',
'detail' => 'detail'
]
],
NULL => [
Route::FILTER_IN => static function (array $parameters) use ($worksRepository): array {
$parameters['work_id'] = array_search($parameters['work_id'], $worksRepository->getWorkBySlug());
return $parameters;
},
Route::FILTER_OUT => static function (array $parameters) use ($worksRepository): array {
bdump($worksRepository->getWorkBySlug());
$parameters['work_id'] = $worksRepository->getWorkBySlug()[$parameters['work_id']];
return $parameters;
},
]
]);
Presenter
public function actionDetail(int $work_id){
$work = $this->worksRepository->getWork($work_id);
if ($work_id){
$this->template->work = $work;
}else{
$this->redirect(':Front:Homepage:');
}
}
DB:
work_id int(11) Auto Increment
title varchar(255)
code varchar(255)
client varchar(255)
url varchar(255)
date datetime
content text
images_count int(1)
A můj cíl je aby místo blbého ?work_id=1 mi to vrátilo
název práce tudíž title
Ale když už jsem se dostal do fáze kdy mám funkci
$worksRepository->getWorkBySlug()
Která dělá
/**
* @return array
*/
public function getWorkBySlug ()
{
return $this->database->table(self::TABLE_NAME)->fetchPairs('work_id','title');
}
Tak mám problém že to prostě nezná Undefined index:
work_id přitom s ním pracuji a pokud si vrátím
$parameters
tak mi to vrátí 2× arrey a to
action => "default"
presenter => "Front:Works"
a 2
work_id => 1
action => "detail"
presenter => "Front:Works"
Takže chyba bude nejspíše v tom že to vrátí 2 a jeden neobsahuje to work_id a druhý ano ale jak teď zajistit aby to v případě toho prvního kde chybí bylo třeba null aby to prostě fungovalo.
Snad sem to už napsal tak aby jste to pochopily.
Díky
- David Matějka
- Moderator | 6445
ale jak teď zajistit aby to v případě toho prvního kde chybí bylo třeba null aby to prostě fungovalo.
to neumis napsat if (isset(..))
? ale pokud to ta jedna
(default) routa nevyzaduje, tak tu definici rozdel na dve – jednu pro
default, ktera nema ten parametr work_id a druhou pro detail, ktera ten
parametr ma
- jAkErCZ
- Člen | 322
David Matějka napsal(a):
ale jak teď zajistit aby to v případě toho prvního kde chybí bylo třeba null aby to prostě fungovalo.
to neumis napsat
if (isset(..))
? ale pokud to ta jedna (default) routa nevyzaduje, tak tu definici rozdel na dve – jednu pro default, ktera nema ten parametr work_id a druhou pro detail, ktera ten parametr ma
Bomba tohle funguje jen dotaz když si práce vracím
$this->database->table(self::TABLE_NAME)->fetchPairs('work_id','title');
Tak nějaký nápad jak na to implementovat webalize?
- David Matějka
- Moderator | 6445
viz muj prispevek nahore
a vytahnout si z databaze vsechny prispevky, abys zjistil, kde slug odpovida, je velmi neefektivni. udelej si v databazi sloupecek slug
- Kamil Valenta
- Člen | 822
Ukládej si v db title a zvlášť webalizovaný slug (na něm patrně i databázový index).