Administrace jako extension

dehtak
Člen | 113
+
0
-

Ahoj,
Chteli bych udelat administraci jako rozsireni. Ale moc se v tom extensions nevyznam. Mohl by mi nekdo udelat priklad jak udelat extension aby si to pak nacetlo svuj router a svoje configy. Zrejme asi nakej create container tam bude.

Toanir
Člen | 57
+
0
-

Ahoj,

Já modularitu řeším nějak následovně:

Nepovažuju to za nějakým způsobem kanonický řešení ale takhle se mi to vesměs líbí… Ještě to má značnej prostor pro zlepšování a ve výsledku bych se chtěl vyhnout explicitnímu routovacímu modulu a místo toho je zabalit do jakejchsi aplikačních modulů ale to je cesta, kterou jsem si ještě neprošlápl a ještě nevím, jestli se mi bude líbit…

Nicméně bych řekl že tenhle přístup může zhruba sloužit jako inspirace, jak to zadrátovat dohromady. :)

David Matějka
Moderator | 6445
+
0
-

ahoj,
v dokumentaci najdes vsechny zakladni veci https://doc.nette.org/…n/extensions – vcetne konfigurace, nacitani sluzeb z neonu atd.

na pokrocilejsi veci se muzes kouknout do ruznych existujicich extensions, treba v kdyby/console muzes videt, jak se necha vyresit router

Toanir
Člen | 57
+
0
-

Hehe,,, vlastně jsem si uvědomil, že úplně nevím čeho se snažíš dosáhnout. To se prej hodí když chce člověk radit. :P

Jaký je tvůj aktuální stav (používáš Nette aplikaci se statickým routerem? nebo nějaké poselství?) a co od práce s extensionou čekáš?

dehtak
Člen | 113
+
0
-

Jde mi o to mit administraci pro vice domen. Skousel jsem to prez module ale neni to ono. Snazim se o to, udelat administraci jako samostatnou aplikaci, ale aby zdedila databazovy pripojeni od urcity domeny. Skusim to namalovat k pochopeni. Dejme tomu ze to je hosting, mam tam 3 weby

Web 1 = domain1.cz
	-app
	-tmp
	-log
	-www
web 2 = domain2.cz
	-app
	-tmp
	-log
	-www
web 3 = domain3.cz
	-app
	-tmp
	-log
	-www
Administace
	-app
	-tmp
	-log

Administrace bude vzdy volana domain1.cz/admin nebo domain2.cz/admin, nebo prez subdomenu admin.domain1.cz (administrace nepotrebuje slozku www jelikoz se index nacita z www prislusnyho webu, tudiz nemuze mit svuj boostrap) a tady je kamen urazu. Kdyz sem to mel ale jako modul tak %appDir% byl vzdy treba web1/app a takze pak bych musel spat veci co patri do administrace do web1/app slozky. Jelikoz nektery extension proste tu appdir vyzaduji.

Chci aby se Administrace chovala jako app prezentery routry config , fabricky atd..
Nevim jak toho docilit uz si nad tim lamu hlavu nekolik tydnu. Administrace je vlastne porad to same jen pracuje pak s jinym db pripojenim prislusnyho webu. Popripade kdyby nakej web mel neco extra navic tak to nejak pridat pred extension
Admin muze bejt klidne i ve vendoru to je jedno. Ale prijde mi zbytecny cpat administraci (jedno a to same) do kazdy app slozky prislusnyho webu.

Proste chci udelat novej web udelam sablonu zkopiruju app od jinyho webu udelam db pripojeni prdnu na hosting hotovo.
V administraci ponastavim.

Editoval dehtak (27. 4. 2020 22:08)

romanm
Člen | 27
+
0
-

Nevím zda chápu celé workflow. Co kdyby administrace byla samostatná appka a jen by se připojovala do databází dle domény/projektu?

Pokud jsou aplikace stejné, jen se liší třeba šablonou a data jsou v DB, tak by to tak šlo ne?

dehtak
Člen | 113
+
0
-

O to mi jde ale jak docilim toho ze kdyz zadam adresu domain1.cz/admin aby se nacetla ta administrace
jedine udelat do indexu nakej prepinac kterej budre prepinat boostrapy. Tohle uz me taky napadlo.

Toanir
Člen | 57
+
0
-

Nezkoušel sis hrát s rewrite pravidlama cílovejch aplikací? Mohl bys mít administraci jako úplně běžnou standalone appku, která bude rozpoznávat víc domén…

Standardně nette běží v nastavení že se ti vše, co není soubor, pŕepisuje na www/index.php. Před tohle přepsání bys mohl ještě přidat, že když máš na začátku url /admin, přepíšeš to na, třeba ../administrace/www.

Pak by to šlo vyřešit ještě že by jednotlivý aplikace integrovaly administraci jako balíček ale bylo by to docela dost konfigurace.

dehtak
Člen | 113
+
0
-

vidite udelat to v rewrite me vubec nenapadlo. Ale jako balicek to udelat mi pripada jako nejrozumenjsi reseni.

Editoval dehtak (28. 4. 2020 11:29)

Toanir
Člen | 57
+
0
-

Hehe, řešení balíčkem jsem začal rozepisovat a pak jsem se v tom zamotal a kydž jsem si znovu přečetl tvojí zprávu s přepínačem v bootstrapu, napadl mě přepínač ještě před ním v podobě rewritu. :P

Jestli si zběhlý v práci s composerem, doporučuju mrknout na vlastní repozitář cestou na disku ( https://getcomposer.org/…ositories.md#path ), díky tomu bys měl být schopnej nainstalovat si administraci jako běžnou závislost.

Potom se ti bude hodit úprava routeru, viz kód z kdyby/console, který posílal David Matějka o pár příspěvků výše. Pravděpodobně si v rámci Administrace budeš chtít vytvořit RouteList a dát tomu jedinečný název modulu ( třeba „Admin“ :P ). Pak by sis měl nastavit mapování presenterů pro danej modul v konfiguraci application.mapping, kdy přidáš svůj pojmenovaný modul jako mapu k presenterům administrace, tj před výchozí mapování přidáš třeba

Admin: SexyAdministrace/Presenters/*Presenter

Potom routy z tý pojmenovaný RouteList budou překládaný na presentery v daným namespace.

Myslím že by to takhle mělo stačit, pokud se na něčem zasekneš nebo jsem něco nepopsal dostatečně, určo se ozvi.

dehtak
Člen | 113
+
0
-

Diky moc, zkusim si s tim pohrat a kdyz tak pisnu

dehtak
Člen | 113
+
0
-

Tak nakonec jsem to nechal jako model tu administraci.
muj boostrap

namespace App;

use Nette\Configurator;


class Bootstrap {
    public static function boot(): Configurator{
        $configurator = new Configurator;

	$configurator->enableTracy(DIR_ROOT . '/log');

	$configurator->setTimeZone('Europe/Prague');
	$configurator->setTempDirectory(DIR_ROOT . '/temp');

	$configurator->createRobotLoader()
            ->addDirectory(__DIR__)
            ->addDirectory(realpath(DIR_ROOT.'/../Admin'))
            ->register();

	$configurator->addConfig(DIR_ROOT . '/config/common.neon');
	$configurator->addConfig(DIR_ROOT . '/config/local.neon');
        $configurator->addConfig(DIR_ROOT . '/../Admin/config/admin.neon');

	return $configurator;
    }
}

potreboval bych udelat nakou fabriku na detekovani Modelu. neco jako getModelName podle toho jakej modej je zrovna nacten.
Ale z ceho to vytahnout? Mimochodem ten extesions sem vzdal v tom se vubec nevyznam.

Editoval dehtak (29. 4. 2020 15:08)

Toanir
Člen | 57
+
0
-

Týjo… to s tím RobotLoaderem vypadá šikovně :) Mě to nenepadlo, páč se RobotLoaderu vyhejbám jak čert kříži a opírám se o autoloading z composeru.

Máš to dělaný tak, že každá z těch aplikací má vlastní bootstrap a vlastní konfiguráky? Jeslti jo, mohl bys ten model nasypat rovnou do konfigurace podle který bys volal/vytvářel servisky z Administrace. Pak by to mohlo vypadat tak že bys měl

# app1/config/common.neon
parameters:
  applicationModel: "Money stuff"

# app2/config/common.neon
parameters:
  applicationModel: "Very household"

# administration/config/common.neon
services:
  - Administration/AppModel/AppModelFacade(%applicationModel%)

Jinak z těch extension si nedělej těžkou hlavu… V podstatě slouží k pohodlnýmu zabalení funkcionality a drátování do úhlednýho drop-in balíčku a to zadrátování potom vypadá naprosto libově…
Většinu věcí co se týče businessu bys měl dokázat i bez nich.

dehtak
Člen | 113
+
0
-

Kazda aplikace ma svuj boostrap krome teda admina. To co mi navrhujes nemuzu pouzit, ja prave potrebuju detekovat Front Modul od Admin modul.
Kazdej web ma front modul a admin modul.

Prave potrebuju tu fabricku abych mohl par veci oddelit ktere bych potreboval. Dejme tomu ze budu mit translator a jazyky pro admina ve slozce Admin/lang. Aplikacce treba translator mit vubec nebude. Diky ty fabricce si zjistim jakej je nactenej modul a pak tomu translatoru podle toho predam slozku kde ma hledat jazykovy soubory.

Editoval dehtak (29. 4. 2020 18:17)

CZechBoY
Člen | 3608
+
0
-

btw Funkcionalita robotloaderu a jakyhokoliv autoloaderu by mela byt stejna. Co te udivuje na pouziti robotloaderu?

Toanir
Člen | 57
+
0
-

Hmm, takže detekuješ modUl a ne modEl? :P

Detekci modulu bys imho měl řešit už u routeru, kde si zaregistruješ routy pro admin modul souběžně s ostatníma… Mohlo by to potom vypadat nějak následovně:

// web1/app/Routing/RouterFactory.php
namespace App\Routing;
class RouterFactory {
  private $adminRouter;

  public function __construct(IRouter $adminRouter) {
    $this->adminRouter = $adminRouter;
  }

  public function create(IRouter $adminRouter) {
    $routes = new \Nette\Application\Routing\RouteList();

    $routes[] = $this->adminRouter;
    $routes[] = $this->createAppRoutes();

    return $routes;
  }

  private function creteAppRoutes() {
    $routes = new RouteList('Front');
    $router->addRoute('<presenter>/<action>', ...);

    return $router;
  }
}

//Admin/src/Routing/RouterFactory
namespace Admin\Routing;

class RouterFactory {

  public static function createRouter() {
    $routes = new \Nette\Application\RouteList('Admin');
    $routes->addRoute('admin/<presenter>/<action>', ...);

    return $routes;
  }
}

a v konfigu to pak akorát zadrátuješ

services:
  routerFactory: App\Routing\RouterFactory(Admin\Routing\RouterFactory::create())
  router: @routerFactory::create

Nezapomeň, že pro moduly musíš mít nstavený application.mapping viz pŕedchozí příspěvek.

Toanir
Člen | 57
+
0
-

Ad RobotLoader, jednoduše na něj nejsem zvyklý a zapomněl jsem že je takhle po ruce. Standardně si na všechno vystačím s composer autoloaderem. RobotLoader se chová jako taková composeří classmapa s automatickým obnovováním, což se pro tenhle případ náramně hodí.

dehtak
Člen | 113
+
0
-

To je vytvoreni routru trosku jinak, ja ho mam takhle

namespace App\Factory;

use Nette;
use Nette\Application\Routers\RouteList;

final class Router
{
	use Nette\StaticClass;

	public static function create(): RouteList{
            $router = new RouteList;
            $router->withModule('Admin')
				->addRoute('admin/<presenter>/<action>[/<id>]', 'Home:default');
            $router->withModule('App')
				->addRoute('<presenter>/<action>[/<id>]', 'Home:default');
            return $router;

	}
}

Nejak sem z toho tvyho routru nepochopil jak si detekuju modul.
Nebo me tak jeste napadlo on by se nemusel detekovat modul stacilo by aby si kazdej modul nacet config sam pro sebe aby nebyly slouceny. To by bylo asi tak nejlepsi. Mimimochodem jestli sem psal nekde model tak se omlouvam me uz se to vsechno plete.

Editoval dehtak (30. 4. 2020 13:59)

Toanir
Člen | 57
+
0
-

Hehe,, s modulem to všechno dává větší smysl :)

V mým příkladu je to akorát rozházený do různejch tříd a svázaný skrze DI. Mělo by to dělat vesměs to samý jako tvoje ukázka. Já název modulu předávám konstruktorem a ty pro to využíváš fluentní skládání.

Jestli tvůj router vypadá takhle, měl bys mít vystaráno.. alespoň v části routeru. V zachycenejch routách bys měl mít v Requestu parametr module vedle parametrů presenter a action a vlastně všech dalších parametrů, který ti router zachytává. Jak s ním chceš teď naložít? Respektive jaká je teď tvoje situace? Načte se ti presenter z administrace?

Jen pro shrnutí probublání požadavku aplikací vypadá zhruba nějak tahke:

  • HttpRequest se prožene vytvořeným routerem, při matchnutí se vytvoří (aplikační) Request, který obsahuje všechno, co dostane od routeru
  • Na základě nakonfigurovanýho application.mapping a parametru presenter (a případně module) se vytvoří Presenter
  • Presenter zchroupe odpověď a vrací (aplikační) Response díky logice, co do něj nacpeš, a čassto díky Latte
  • Aplikace si zmanažuje Response a odesílá HttpResponse
CZechBoY
Člen | 3608
+
0
-

@Toanir Pravda, když děláš stále nový a nový třídy tak je dumpování classmapy zdlouhavý, ale když používáš PSR-0/4 tak to není vlastně vůbec potřeba pokud se nepletu.

dehtak
Člen | 113
+
0
-

tak jsem to udelal takhle nevim jestli je to dobre

use Nette\Application\Application;

class Modul {
        private $modul;
        private $modulDir;

	public function __construct(Nette\Application\Application $app){
            $request = $app->getRequests();
            $name = $request[0]->getPresenterName();

            $pos = strrpos($name, ':');
            $this->modul = substr($name, 0, $pos);

            $this->modulDir = $this->modul=='App' ? realpath(DIR_ROOT.'/App') : realpath(DIR_ROOT.'/../'.$this->modul);
	}
}

v configu mam tohle

services:
	modul: Modul

Editoval dehtak (30. 4. 2020 23:33)

Toanir
Člen | 57
+
0
-

@ autoloading, jj na nových projektech se opírám pouze na PSR-4 a zároveň se snažím dělat moduly co nejmělčí moduly což mě ve výsledku nutí dávat věci tam, kam patří. :P

@ Modul tady šaháš už na dost věcí. Teoreticky vzato by to mělo fungovat ve většině případů. Průšvih můźe nastat, pokud budeš dělat například forward do jinýho modulu, pak budeš vázanej na modul ve kterým byl první request. Aby tohle fungovalo vždy, zabal to do funkce, která vždy vezme poslední request a podle toho se bude orientovat, tj tvoje třída by mohla vypadat takhle:

class Modul {
    private $application;

	public function __construct(Nette\Application\Application $app){
        $this->application = $app;
    }

    public function getModuleDirForCurrentRequest() {
        $moduleName = $this->getModuleNameOfCurrentRequest();
        return $this->getModuleDirectory($moduleName);
	}

    private function getModuleNameOfCurrentRequest() {
        $request = $this->application->getRequests();
        $name = end($request)->getPresenterName();

        $pos = strrpos($name, ':');
        return substr($name, 0, $pos);
    }

    private function getModuleDirectory(string $module) {
        return $module =='App' ? realpath(DIR_ROOT.'/App') : realpath(DIR_ROOT.'/../'.$module);
    }
}

Dovolil jsem si ukázku rozsekat na kratší metody s exlicitním pojmenováním aby bylo úplně jasný, co dělají… Celkově mi to ale připadá trošičku pochybný a asi není úplně košér takhle pracovat s aplikací.

Stále jsem úplně nepochopil, co s tím adresářem chceš vytvářet. Můžeš to nějak blíže nastínit? Třeba pro tvůj problém existuje jednodušší řešení

Editoval Toanir (1. 5. 2020 19:36)

dehtak
Člen | 113
+
0
-

ja uz sem to vyresil uplne jinak, prez htaccess jak mi radily na zacatku. Ted to mam jako samostatnou aplikaci vyresil jsem i nacteni db configu od apllikaci. Uz to dal resit nebudu. Dlouho sem se nad tim trapil. Pokud chces vedet jak tak to sem muzu hodit.

Editoval dehtak (1. 5. 2020 21:56)