Kam umiestniť $acl = new Nette\Security\Permission;
- Čamo
- Člen | 798
enumag:
Hm, mňa to ťahá k tomu, čo napísal v tom vlákne Šaman nad tebou. Je to
síce asi to znásilnenie dedičnosti, ale je to také minimalistické. Žiadny
medzikrok.
Dalo by sa to spraviť tak,že by to fungovalo ako RouterFactory? Že by to spracoval bootstrap automaticky? Viac mi to pripadá ako konfigurácia aplikácie, než ako nejaká služba. Ale možno úplne trepem…
PS:
Potreboval by som vysvetliť ten neon čo tam máš:
services:
app.authorizatorFactory: App\AuthorizatorFactory
app.authorizator: @app.authorizatorFactory::create
načo je to app. + celý ten druhý riadok. Z neonu mám stále dosť guláš.
Editoval Čamo (20. 1. 2015 23:54)
- Filip Procházka
- Moderator | 4668
Souhlasím s @enumag – řešení s factory je dobré řešení a
rozhodně je čistější než dědit Permission
objekt, jenom abys
ho v konstruktoru nastavil.
Ta definice v services
znamená
- zaregistruj službu
app.authorizatorFactory
, jejíž třída budeApp\AuthorizatorFactory
- zaregistruj službu
app.authorizator
, která se vytváří zavoláním metodycreate
nad objektem, který získáš ze službyapp.authorizatorFactory
Přepsáno na procedurální kód by to vypadalo zjednodušeně takto nějak
$factory = new App\AuthorizatorFactory;
$container->addService('app.authorizator', $factory->create());
- Čamo
- Člen | 798
Díky za odpovede. Snáď som to pochopil.
Ale dedenie sa používa aj vtedy, keď sa prepisuje nejaká metóda. V tomto prípade je to konštruktor nie?
Filip Procházka
Ten kód by nemal vyzerať skôr takto?
$container->addService('factory', new App\AuthorizatorFactory());
$container->addService('app.authorizator', $container->factory->create());
Tie prefixi som si už prečítal.
Díky.
Editoval Čamo (21. 1. 2015 8:23)
- enumag
- Člen | 2118
@Čamo V podstatě ano, Filip to zjednodušil protože AuthorizatorFactory je službou vlastně jen proto aby se to volání create dalo nastavit přes neon. V procedurálním zápisu to nutné není. Reálně v aplikaci tu službu factory potřebovat nebudeš, injectneš si přímo ten authorizator.
Editoval enumag (21. 1. 2015 9:31)
- Šaman
- Člen | 2659
Čamo napsal(a):
enumag:
Hm, mňa to ťahá k tomu, čo napísal v tom vlákne Šaman nad tebou. Je to síce asi to znásilnenie dedičnosti, ale je to také minimalistické. Žiadny medzikrok.
No, znásilnění dědičnosti to není (můj AccessList JE konkretizovaná Permission), ale spíš jde o to, že je zbytečné vytvářet novou třídu děděním, když na to stačí továrnička (stejná situace je ve formulářích).
Tu továrnu pak stejně potřebuju (ACL by ještě mohla být služba, ale formuláře chci určitě vytvářet továrnou, abych jich mohl mít několik), tak si rovnou napíšu továrnu, co mi nakonfiguruje a vrátí konkrétní instanci, než nejprve dědit, vytvořit jednoúčelovou classu a pak si stejně nechat vygenerovat továrnu (vpodstatě prázdnou).
Dokud máš dojem, že se tu bavíme na zbytečně akademické úrovni, nebo dokud jsi rád, že rozchodíš aspoň jeden způsob, tak oba jsou dostatečně dobré. Ale dneska už používám přednostně @enumagův způsob všude, kde potřebuju nakonfigurovat a vrátit konkrétní instanci nějaké třídy – za best practise bych bral jeho řešení.
- David Grudl
- Nette Core | 8218
Já bych to udělal jako @enumag a klidně i použil místo metody funkci (resp. statickou metodu, protože funkce neumí autoloading):
class AuthorizatorFactory
{
/**
* @return \Nette\Security\IAuthorizator
*/
public static function create()
{
...
return $acl;
}
}
Protože pak je snadnější zápis do configu
services:
app.authorizator: App\AuthorizatorFactory::create
- enumag
- Člen | 2118
@Šaman Úplně stejný případ jako jsem odpovídal Davidovi. Pokud v RouterFactory nepotřebuješ závislosti, klidně si to tak přepiš. Já si factory nechávám jako službu vždy, ale dělám to jen ze setrvačnosti – respektive abych so nemusel měnit až budu závislost potřebovat.
EDIT: Teoreticky kdybys závislosti dal jako argumenty té statické funkce tak by to zřejmě fungovalo, ale to už se mi více zamlouvá normální třída a konstruktor.
Editoval enumag (21. 1. 2015 15:36)
- David Grudl
- Nette Core | 8218
@enumag: službu si klidně nechám injectnout do statické funkce:
/**
* @return \Nette\Security\IAuthorizator
*/
public static function create(Nette\Database\Connection $db)
{
...
}
@Šaman už se stalo
- Filip Procházka
- Moderator | 4668
Čamo napsal(a):
Ale dedenie sa používa aj vtedy, keď sa prepisuje nejaká metóda.
Né vždy. A né vždy je vhodné přepisovat metody, občas (=skoro vždy) je lepší použít kompozici a nebo jiné techniky.
V tomto prípade je to konštruktor nie?
To je právě strašný omyl. Dědit třídu abys ji nastavil v konstruktoru je brutální prasárna. Od toho jsou továrny a konfigurace.
- David Matějka
- Moderator | 6445
doplnim jen obligatni „inheritance is the root of all evil“ :)
@DavidGrudl to sice hezky funguje, kdyz je to pod spravou DIC, problem by byl mimo – zatimco u factory s nestatickou metodou si proste vyzadas onu FooFactory a zavolas create, u te staticke metody by jeji uzivatel musel znat a ziskavat vsechny jeji zavislosti, aby ji vubec mohl zavolat…
- Čamo
- Člen | 798
Paráda funguje to… (až na jednu maličkosť č.4)
Ak by mal niekto náladu :P
- Tá závislosť služby na DB sa musí povoliť v neone, aby sa to dalo injektovať, že ano?
- Prečo je konfigurácia v konštruktore „brutálna prasárna“?
- Ako by to vyzeralo bez možnosti injektovať(tú databázu)?
- Mám kód:
$permission->addRole('admin', 'redactor');
...
prihlási sa admin
...
if($user->isInRole('admin') { echo 'admin' }
if($user->isInRole('redactor') { echo 'redactor' }
Vypíše iba admin. Dedičnosť rolí to teda nedokáže zohľadniť?
Editoval Čamo (21. 1. 2015 20:42)
- David Matějka
- Moderator | 6445
@Čamo
- pokud pouzivas ten zpusob od @enumag, tak pouze v konstruktoru te factory uved zavislost na DB, o zbytek se postara autowiring.
- je to zneuziti dedicnosti. Zbytecne tam vytvaris nejakou hierarchii trid, kdyz to vubec neni potreba. Factory pattern je mnohem tvarnejsi. Prece taky nedelas, ze by sis podedil Nette\Database\Connection, nazval to MojeSpojeni a v konstruktoru to nakonfiguroval :)) (ano, je to trochu ad absurdum, ale…).
- nechapu…
- bohuzel, dedicnost roli je vlastnost Nette\Security\Permission. Metoda
isInRole, ktera je v Nette\Security\User o tom nevi a proto pracuje pouze
s temi rolemi v identie. Pokud vsak budes pouzivat
isAllowed
, tak se dedicnost roli zohledni.
Editoval matej21 (21. 1. 2015 20:58)
- David Grudl
- Nette Core | 8218
@matej21 přesně tak. Záleží na tom, jestli chci mít v DIC továrnu na ACL nebo ACL, a podle toho to napíšu. Pokud továrnu nepotřebuju, je zbytečné ji vytvářet.
Třeba v případě routeru jsem se s potřebou mít na něj v DIC továrnu zatím nesetkal, předpokládám, že je to hodně vzácné, proto jsem ji ze sandboxu odstranil.
- Šaman
- Člen | 2659
Čamo napsal(a):
4. Mám kód:
$permission->addRole('admin', 'redactor'); ... prihlási sa admin ... if($user->isInRole('admin') { echo 'admin' } if($user->isInRole('redactor') { echo 'redactor' }
Vypíše iba admin. Dedičnosť rolí to teda nedokáže zohľadniť?
Dědičnost rolí funguje, jak už psal @matej21, jen co se týče
opravnění. Ber to tak, že admin dědí práva redaktora, nikoliv
tak, že admin je redaktor.
$user->isInRole()
ti ověří, zda daný uživatel má přímo
přidělenou nějakou roli. Pokud budeš chtít provádět jednoduché řízení
práv na základě rolí aka if($user->isInRole()) {…}
, tak
s dědičností nepočítej. V tu chvíli ani objekt Permission
nepotřebuješ.