Pridať routu v extension na základe modulu
- iNviNho
- Člen | 352
Ahojte,
Ked zaregistrujem ArticleExtension
extensions:
...
article: App\AdminModule\ArticleModule\ArticleExtension(@Nette\Application\Application)
tak by som chcel, aby sa mi okrem závislostí pridali aj routy do routelist. Skúšal som tam dostať Nette\Application\Application odkiaľ by som si zobral router, ale nedokázal som ho do konštruktoru nejako dostať…
<?php
class ArticleExtension extends \Nette\DI\CompilerExtension {
/** @var Nette\Application\Application */
private $application;
public function __construct(\Nette\Application\Application $application) {
$this->application = $application;
}
public function loadConfiguration() {
dump($this->application);
die();
$builder = $this->getContainerBuilder();
$builder->addDefinition($this->prefix('services'))
->setClass('App\Services\ArticleService');
$builder->addDefinition($this->prefix('repository'))
->setClass('App\Repositories\ArticleRepository');
$builder->addDefinition($this->prefix("formFactory"))
->setClass("App\Factories\ArticleFormFactory");
}
}
?>
Viete mi poradiť ako cca na to?
Ďakujem
Editoval iNviNho (13. 4. 2016 19:39)
- iNviNho
- Člen | 352
Felix napsal(a):
Vubec nepotrebujes Application, udelej si vlastni router nebo pouzij predpripravenej.
V extension si to vytahni pres builder. Nepredavej jako zavislost.
Poradíš mi prosím ako to vytiahnem cez ContainerBuilder ?
- Oli
- Člen | 1215
Tím addDefinition bys přidal novou službu, ty ji chceš vytáhnout. Takze getDefinition
Takže třeba pro mailer používám:
$builder->getDefinition('nette.mailer')
->setClass('\Nette\Mail\SmtpMailer', [$config['SMTP']]);
- iNviNho
- Člen | 352
Stále nie som o nič múdrejší.
Mám jednoducho RouterFactory:
<?php
/**
* Router factory.
*/
class RouterFactory
{
/**
* @return \Nette\Application\IRouter
*/
public static function createRouter()
{
$router = new RouteList;
// default router
$router[] = $adminSubRouter = new RouteList('Admin:Homepage');
$adminSubRouter[] = new Route('[<locale=sk sk|en>/]admin/<action>[/<id>]', 'Homepage:default');
return $router;
}
}
?>
A ja by som chcel, že ked registrujem extension, tak by sa stale niečo takéto:
<?php
public function loadConfiguration() {
$builder = $this->getContainerBuilder();
dump($builder->getDefinition("routing.router"));
$builder->addDefinition($this->prefix('service'))
->setClass('App\Services\ArticleService');
$builder->addDefinition($this->prefix('repository'))
->setClass('App\Repositories\ArticleRepository');
$builder->addDefinition($this->prefix("formFactory"))
->setClass("App\Factories\ArticleFormFactory");
// router for ArticleModule
// nejako vytiahnem router, pridám routu
$router[] = $adminSubRouter = new RouteList('Admin:Article');
$adminSubRouter[] = new Route('[<locale=sk sk|en>/]admin/article/<action>[/<id>]', 'Article:default');
}
?>
Problém je cca v tom, že ten router sa vytvára staticky, čiže asi môžem do neho zasahovať až po jeho vytvorení, čiže možno v metode afterCompile, ale neviem neviem
- Martk
- Člen | 661
Odstraníš slovo static. Mělo by to vypadat nějak takhle
/**
* Router factory.
*/
class RouterFactory
{
private $router;
public function __construct() {
$this->router = new RouteList();
}
public function append($mask, $metadata = [], $flags = 0) {
$this->router[] = new Route($mask, $metadata, $flags);
}
/**
* @return \Nette\Application\IRouter
*/
public function createRouter() {
$router = $this->router;
// default router
$router[] = $adminSubRouter = new RouteList('Admin:Homepage');
$adminSubRouter[] = new Route('[<locale=sk sk|en>/]admin/<action>[/<id>]', 'Homepage:default');
return $router;
}
}
V extensions:
$builder->getDefinition('router')
->addSetup('append', ['[<locale=sk sk|en>/]admin/article/<action>[/<id>]', 'Article:default'])
Pro tohle jsem si vytvořil balíček, který řadí a přidává routy podle modulů a priorit.
Editoval Antik (14. 4. 2016 10:26)
- iNviNho
- Člen | 352
Antik napsal(a):
Odstraníš slovo static. Mělo by to vypadat nějak takhle
/** * Router factory. */ class RouterFactory { private $router; public function __construct() { $this->router = new RouteList(); } public function append($mask, $metadata = [], $flags = 0) { $this->router[] = new Route($mask, $metadata, $flags); } /** * @return \Nette\Application\IRouter */ public function createRouter() { $router = $this->router; // default router $router[] = $adminSubRouter = new RouteList('Admin:Homepage'); $adminSubRouter[] = new Route('[<locale=sk sk|en>/]admin/<action>[/<id>]', 'Homepage:default'); return $router; } }
V extensions:
$builder->getDefinition('router') ->addSetup('append', ['[<locale=sk sk|en>/]admin/article/<action>[/<id>]', 'Article:default'])
Pro tohle jsem si vytvořil balíček, který řadí a přidává routy podle modulů a priorit.
Perfiš, idem vyskúšať!
Vyzerá to presne tak, ako som si to predstavoval :)
- iNviNho
- Člen | 352
Tak skúšal som to:
# ROUTER
routerFactory: App\RouterFactory
router: @routerFactory::createRouter
RouterFactory
**
* Router factory
*/
class RouterFactory
{
/**
* @var RouteList
*/
private $router;
public function __construct() {
$this->router = new RouteList();
}
/**
* Inserts route list to current router
* @param type $routelist
* @param type $routemask
* @param type $destination
*/
public function append($routelist, $routemask, $destination) {
$newRouteList = new RouteList($routelist);
$newRoute = new Route($routemask, $destination);
$newRouteList[] = $newRoute;
$this->router[] = $newRouteList;
}
/**
* @return IRouter
*/
public function createRouter() {
$router = $this->getRouter();
return $router;
}
/**
* Returns current router
* @return RouteList
*/
public function getRouter() {
return $this->router;
}
}
A napr. HomepageExtension
class HomepageExtension extends DefaultModuleExtension {
public function loadConfiguration() {
$builder = $this->getContainerBuilder();
$builder->getDefinition("router")
->addSetup('append', ['Admin:Homepage', '[<locale=sk sk|en>/]admin/<action>[/<id>]', 'Homepage:default']);
}
}
Dostávam error: Call to undefined method Nette\Application\Routers\RouteList::append
/**
3492: * @return Nette\Application\IRouter
3493: */
3494: public function createServiceRouting__router()
3495: {
3496: $service = $this->getService('routerFactory')->createRouter();
3497: if (!$service instanceof Nette\Application\IRouter) {
3498: throw new Nette\UnexpectedValueException('Unable to create service \'routing.router\', value returned by factory is not Nette\Application\IRouter type.');
3499: }
3500: $service->append('Admin:Homepage', '[<locale=sk sk|en>/]admin/<action>[/<id>]', 'Homepage:default');
3501: return $service;
3502: }
Chybe rozumiem, kedže createRouter už vracia IRouter, čiže ked sa bude táto funkcia spúšťať routy už musia byť pripravené.
Nerozumiem teda prečo sa nedokážem cez containerBuilder dostať, resp. tam neexistuje routerFactory, kde by som dokázal pridávať tie routy…
- iNviNho
- Člen | 352
Ok podarilo sa mi to rozbehnúť:
Config.neon
routerFactory: App\RouterFactory(%createdRoutes%)
router: @routerFactory::createRouter
RouterFactory
class RouterFactory
{
/**
* @var RouteList
*/
private $router;
public function __construct($createdRoutes) {
$this->router = new RouteList();
foreach ($createdRoutes as $routeList) {
$this->addRouteList($routeList);
}
}
/**
* Add routelist to router
* @param RouteList $routeList
*/
private function addRouteList($routeList) {
$this->router[] = $routeList;
}
/**
* @return IRouter
*/
public function createRouter() {
$router = $this->getRouter();
return $router;
}
/**
* Returns current router
* @return RouteList
*/
public function getRouter() {
return $this->router;
}
}
HomepageExtension
class HomepageExtension extends DefaultModuleExtension {
public function loadConfiguration() {
$this->appendRoute('Admin:Homepage', '[<locale=sk sk|en>/]admin/<action>[/<id>]', 'Homepage:default');
}
}
Dedí od DefaultModuleExtension, ktorá má konkrétnu metodu appendRoute
/**
* Inserts route list to current router
* @param type $routelist
* @param type $routemask
* @param type $destination
*/
protected function appendRoute($routelist, $routemask, $destination) {
$newRouteList = new RouteList($routelist);
$newRoute = new Route($routemask, $destination);
$newRouteList[] = $newRoute;
$builder = $this->getContainerBuilder();
$builder->parameters["createdRoutes"][] = $newRouteList;
}
Dúfam, že to niekomu pomôže :)