Pridať routu v extension na základe modulu

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
iNviNho
Člen | 352
+
0
-

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)

Felix
Nette Core | 1196
+
0
-

Vubec nepotrebujes Application, udelej si vlastni router nebo pouzij predpripravenej.

V extension si to vytahni pres builder. Nepredavej jako zavislost.

iNviNho
Člen | 352
+
0
-

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

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

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

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

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

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

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