-
- Notifications
You must be signed in to change notification settings - Fork 116
Description
Version: dev-master
Bug Description
When only modules are used in an app, links cannot be created when only one RouteList is used. Exception saying "Invalid link: No route for Bar:Foo:waldo()" is thrown.
Steps To Reproduce
- Download nette/sandbox
composer install- Move Homepage presenter into a Home module:
-namespace App\Presenters; +namespace App\HomeModule\Presenters;- Create another module with another presenter (and put it into
FooPresenter.phpfor example):
namespace App\BarModule\Presenters; final class FooPresenter extends \App\Presenters\BasePresenter { public function renderWaldo(): void ...- Update RouterFactory to read
$router->addRoute('foobar/<action>', [ 'presenter' => 'Foo', 'action' => 'default', 'module' => 'Bar', ]); $router->addRoute('<presenter>/<action>', [ 'presenter' => 'Homepage', 'action' => 'default', 'module' => 'Home', ]);Note the 'module' key.
- Update
Homepage/default.latteto include
<a n:href=":Bar:Foo:waldo">bar module</a>- Enable debug mode, edit
Bootstrap.php, e.g.:
-//$configurator->setDebugMode('23.75.345.200'); // enable for your remote IP +$configurator->setDebugMode(true); // enable for your remote IP-
Start PHP (see the help in nette/sandbox), and load the page
-
You should see
User Warning
Invalid link: No route for Bar:Foo:waldo()
- Change the router (
RouterFactory.php) code:
-$router->addRoute('foobar/<action>', [ -'presenter' => 'Foo', -'action' => 'default', -'module' => 'Bar', -]); -$router->addRoute('<presenter>/<action>', [ -'presenter' => 'Homepage', -'action' => 'default', -'module' => 'Home', -]); +$routerBar = new RouteList('Bar'); +$routerBar->addRoute('foobar/<action>', [ +'presenter' => 'Foo', +'action' => 'default', +]); +$router->add($routerBar); + +$routerHome = new RouteList('Home'); +$routerHome->addRoute('<presenter>/<action>', [ +'presenter' => 'Homepage', +'action' => 'default', +]); +$router->add($routerHome);Note that module name was moved from the module key to the RouteList constructor and that now, instead of adding a Route, we add a RouteList.
- Load the page in your browser again, no error
Expected Behavior
It works :-) Or the exception is more clear or docs are clear.
Possible Solution
There are several options, not sure which one is the correct one, feedback wanted:
- update docs and say when only modules are used then each module needs to use its own
RouteListwith the module name specified in the constructor - somehow try to make it work as it used to before nette/routing was created
Spent quite some time debugging the problem and this is what helped to fix (and understand) the problem for me:
#208 describes that nette/routing classes have no idea about //modules// and that Application\Routers\RouteList solves that. But this is in constructUrl:
public function constructUrl(array $params, Nette\Http\UrlScript $refUrl): ?string { if ($this->module) { if (strncmp($params[self::PRESENTER_KEY], $this->module, strlen($this->module)) === 0) { $params[self::PRESENTER_KEY] = substr($params[self::PRESENTER_KEY], strlen($this->module)); } else { return null; } } return parent::constructUrl($params, $refUrl); }so if there's no $this->module then it just calls parent::constructUrl which doesn't know anything about modules.
The docs says:
In Nette we can split presenters into modules. Therefore we need to work with those modules in routes. We can use module parameter in Route class:
+
If we have more routes that we want to group together in a module, we can use RouteList with name of module in constructor:
So I tried using the constructor param and it worked.
Honestly I'd be totally fine with just updating the docs (and maybe add a BC warning to nette/application release notes?), let me know I can fix it (just not sure how).
Thanks and sorry for this long bug report, tried to write down all I've learned in the past 2 days or so.