Custom router with many slugs
- dkorpar
- Member | 135
So I have a page with >30.000 urls (>10MB of data) and I'm just
rewrriting legacy router with new of my own.
Now I come to issue with querying/caching, and none of options looks good to
me. When displaying pages if no caching is introduced there's more then
500 queries to database for slugs which is ofcours unnaceptable, and querying
all urls is still not a good option, even when cached it's >10MB RAM on each
request.
These are my possible options that I'm aware of
- Don't use plink macro but output links as href=“/{$product->slug}”
→ currently looks like best option
- Cache all possible slugs to array
→ to much RAM usage
- Cache url by url
→ to much calls per request to cache storage (redis)
- (Legacy way which I'm dropping) having static variable inside router
$urlCache that it's filled from anywhere when querying database for product
list or category list or whatever.
→ Serious break of OOP, not readable at all and not maintainable.
What do you think/suggest? Stick to #1 option or you know something I'm not aware of at all?
- Michal Hlávka
- Member | 190
When product entity has it own property slug, where is the problem to use router mask to create url?
Or, can you send me Route from RouteFactory for url, that you want to make? Probably ill be more able to understand.
Last edited by emptywall (2016-10-03 13:13)
- dkorpar
- Member | 135
I don't know to which presenter this is going in start
I'm querying multiple tables until correct slug is found, so it's not possible
to use router mask.
url basically looks like /{$slug}, and this $slug is not neccesary slug from
product, it can be either product/category/article, and in AppRoute I get
correct presenter/id.
- Michal Hlávka
- Member | 190
So regardless on stability, in routerfactory you are grabbing slug for example like this mask /<slug>, where it will be decided which presenter belongs to this slug. right?
- dkorpar
- Member | 135
This is doing AppRoute (implements \Nette\Application\IRouter), in RouterFactory I'm generating RouteList, one of which is AppRoute. AppRoute determines Presenter and id of entity to show (match) based on url, and opposite function constructUrl() which determines url based on presenter name/id
Last edited by dkorpar (2016-10-03 14:22)
- Jan Tvrdík
- Nette guru | 2595
Don't use plink macro but output links as
href="/{$product->slug}"
Not using routing for seems like the best option to me in this specific case by far.
- Tharos
- Member | 1030
+1 for not using plink
macro.
Maybe I'd consider generation of one URL via router with some placeholder for slug and after that I'd simply replace that placeholder by real slug as many times as needed.
If you expected some special characters in slug, you could also pass it through exactly the same code (closure or whatever) as in routing. The performance should be still good.
Last edited by Tharos (2016-10-03 15:16)
- dkorpar
- Member | 135
So I did something completely different :)
I've change constructUrl function so it actually receives slug instead of id, so
I had to change all instances of plink or n:href through templates so it goes
like “Presenter:Default, $item->slug” instead of “Presenter:Default,
$item->id”, match function remained almost the same…
This way I've got it all covered, but still the problem is that I can't use
plink this, any way of resolving that or?
I know it's bnot a perfect solution, but I find it even better then not using
plink at all, and performance and querying database is not an issue at all
anymore…
- dkorpar
- Member | 135
To make ‘plink this’ work and not querying db 2X for same thing
(I have to query it in router to actually get presenter and there I get id of
item already)
I created class AppRequest extends \Nette\Application\Request and add only one
field id to it and in start of presenter I just have
public function renderDefault($id) {
$id = $this->getRequest()->getId();
It is a bit hack, but works nice, adding new parameter to Request would also add it as querystring and I didn't want that, so I implemented it like that…