Předek presenteru bez vícenásobné dědičnosti
- semtex.989
- Člen | 75
Jak řešíte případ, kdy vytvoříte nějaký obecný presenter (např. AdminPresenter pro Translátor), když pořebujete aby dědil i od BasePresenteru (např. kvůli ověření autentizace, atd.)?
Protože PHP (zatím) neumí vícenásobnou dědičnost, napadá mě jen berličková komponenta alá LookoutControl, což ale není úpně čisté.
Jak to děláte vy?
- semtex.989
- Člen | 75
Tak jsem nějak nepobral. Vícenásobná dědičnost takhle napsat nejde.
Nebo to mám chápat tak, že ten obecný presenter napíšeš takhle
<?php
AdminPresenter extends BasePresenter
?>
A pak si ho podědíš kam potřebuješ takhle?
<?php
MyPresenter extends AdminPresenter
?>
- semtex.989
- Člen | 75
To je právě kámen úrazu, nelze prostě předka navrtdo definovat jako BasePresenter.
Představ si, že onen univerzální presenter na editaci překladů bude:
<?php
// admin presenter translátoru
namespace MyPackage\Translator;
AdminPresenter extends BasePresenter
?>
A já budu používat dělení presenterů, jak popisuje třeba Patrik Votoček: http://www.aceblog.cz/…ndpresenter/
Takže by měl dědit od
<?php
namespace BaseModule;
AdminPresenter extends Nette\Application\UI\Presenter
?>
a místo toho bude hledat \BasePresenter..
Nedá se vymyslet univerzální předek do deklarace třídy.
Editoval semtex.989 (11. 1. 2012 10:57)
- semtex.989
- Člen | 75
No jde o to, že u MyPackage\Translator\AdminPresenter nemůžu do klauzule extends dát třídu, protože ji neznám – předek může být třída \BasePresenter nebo BaseModule\AdminPresenter.
EDIT: nemůžu podědit MyPackage\Translator\AdminPresenter, protože by pak nefungovala kontrola autentizace které BaseModule\AdminPresenter
Editoval semtex.989 (11. 1. 2012 15:20)
- Jan Jakeš
- Člen | 177
semtex.989 napsal(a):
Protože PHP (zatím) neumí vícenásobnou dědičnost
A já pevně doufám, že ani nikdy umět nebude.
Pokud potřebuješ vícenásobnou dědičnost, většinou je chyba
v návrhu. Vícenásobná dědičnost je zlo a dá se bez ní v obejít
(obejde se bez ní např. Java i C#). Pokud potřebuješ třídu s více typy
chování, používá se pro jejich zajištění interface
. Pro
opravdové sdílení chování napříč třídami budou v PHP
5.4 použitelné traits
.
Možná jsem nepochopil úplně přesně, čeho chceš vlastně dosáhnout, ale mám pocit, že ti jde jen o znovupoužitelnost určité části aplikace. Pokud je to tak, slouží k tomu komponenty.
- mkoubik
- Člen | 728
Juan napsal(a):
většinou je chyba v návrhu.
Mimochodem, cituji z https://doc.nette.org/…ibuting/code: „nastínění cesty, jak nahradit u presenterů dědičnost za kompozici“ (je tohle vůbec aktuální?).
- Jan Jakeš
- Člen | 177
mkoubik: Nevím, jak přesně tohle bylo myšleno, ale souhlasím s Ondrou Mirtesem, že často je právě kompozice tím vhodným řešením. Navíc jedním z prostředků, jak se elegantně vypořádat s kompozicí je DI, které je v Nette relativně nově a o nutnosti refaktorizovat Presenter už se párkrát mluvilo. Takže to klidně být aktuální může.
- semtex.989
- Člen | 75
Já vím, že by vícenásobná dědičnost být neměla.
Berte to ale tak, že komponenta nemá view a musí se to řešit
berličkou.
interface z hlediska návrhu toto řeší, ale v praxi prostě nefunguje v tomto schématu i když by dával smysl
<TranslationModule/AdminPresenter> → <MyPackage\Translator\AdminPresenter> → <BaseModule/AdminPresenter>
- semtex.989
- Člen | 75
@22: ale link vždy směřuje na handle, nikoliv na view.
Takže si to musím redirectovat
<?php
TranslatorAdminControl extends Nette\Application\UI\Control
{
/** @persistent */
public $view;
function handleXyz($view){
$this->view = $view;
$this->redirect("this");
}
function render(){
...
}
}
?>
Což je IMHO prostě berlička. Chtěl bych plnohodnotný presenter – představ si, že Administrace bude složitější a nacpat logiku co by krásně dávala smysl v Presenteru musíš nabastlit do Komponenty.
Editoval semtex.989 (12. 1. 2012 10:51)
- 22
- Člen | 1478
Cpát celou administraci do jedné komponenty mi nepřijde úplně
košér..
Komponenty slouží k něčemu trochu jinému. Zdá se mi to celé nějaké
zmatené. Ten handle nechápu vůbec. Render metod můžeš mít X a žádný
handle nepotřebuješ imho. Pokud render řídíš persitentní proměnnou, tak
si v základní render metodě akorát podle parametru voláš jednotlivé
rendery.
- semtex.989
- Člen | 75
@22:
Cpát celou administraci do jedné komponenty mi nepřijde úplně
košér..
No právě proto řeším tu dědičnost. Celou administraci modulu prostě do
komponenty nenacpeš
Ten handle nechápu vůbec…
šlo mi o to, že nejde udělat link na view, pouze link na handle.
Beru to tedy tak, že buď se tohle dá řešit špatně pomocí komponenty, anebo špatně pomocí copy-paste hotového presenteru
Editoval semtex.989 (12. 1. 2012 15:14)
- Patrik Votoček
- Člen | 2221
gmvasek napsal(a):
Pleteš jabka a hrušky. Komponenta nemá viewy.
bullshit… má akorát z principu fungují jinak než v presenteru
- semtex.989
- Člen | 75
@22: Souhlasím, je to typický modul.
A když uděláš modul, tak nemáš potřebu, aby administrační rozhraní
modulu ověřilo zda je přihlášen administrátor?
Tím narážím na to, že přeci někdy musí rodiče.
Editoval semtex.989 (13. 1. 2012 8:53)
- semtex.989
- Člen | 75
@22: Přesně tak. A teď jde o to, jak zajistit aby TranslationModule/AdminPresenter měl předka SecuredPresenter.
- 22
- Člen | 1478
Translation module moc nechápu, překlad by měla mít na starost služba, kterou si zavoláš v případě potřeby.. Nebo spíš, co ma dělat TranslationModule a proč má dědit od secured? Nevím, neznám záměr přesně.
Edit: jinak samozřejmě, pokud nad tím nebudu přemýšlet, tak
SecuredPresenter
dáš jako abstraktního předka před
TranslationModule, od kterého dědíš pak dále.
Editoval 22 (13. 1. 2012 16:57)
- semtex.989
- Člen | 75
@22: Překladač služba je, ale má AdminPresenter, který umožňuje
editace překladů, export do tabulky, apod.
A to je třída MyPackage\TranslationModule\AdminPresenter, která je tedy
součastí knihovny MyPackage a dávám jí do adresáře /libs.
A jde o to jak zajistit, aby u obecného knihovního presenteru zajistit potřebného předka – v našem případě SecuredPreseter.
Už si rozumíme?
- 22
- Člen | 1478
Já nevím, asi bych to řešil jinak.. ale proč nemůže tedy ten tvůj
AdminPresenter dědit od SecuredPresenteru?
V praxi by to bylo tak, že máš BasePresenter, od toho dědí SecuredPresnter
a na ten věsíš celou větev, která má chráněný přístup. Ostatní věci
dědí od BasePresetneru.
Přece i teď ti ten presenter dědí z nějakého BasePresenteru.. nebo použít ACL..
Editoval 22 (14. 1. 2012 11:48)
- semtex.989
- Člen | 75
ale proč nemůže tedy ten tvůj AdminPresenter dědit od SecuredPresenteru?
Představ si, že si napíšeš knihovnu, ta obsahuje Translátor s editačním presenterem:
<?php
namespace MyPackage\Translator;
class AdminPresenter extends BaseModule\SecuredPresenter
?>
tak už si tím vynucuješ konvenci, aby aplikace měla tento presenter – BaseModule\SecuredPresenter
Editoval semtex.989 (14. 1. 2012 17:02)
- semtex.989
- Člen | 75
Bohužel nejsem dobrý na vysvětlování…
Zkusím to naposled a co nejstručněji:
1. Mám nějakou svou aplikaci, kde používám konvenci
dělení presenterů
BaseModule
→ FrontPresenter
→ AdminPresenter
ArticleModule
→ FrontPresenter
→ AdminPresenter
2. Pak mám jinou aplikaci, která používá jednodušší
konvenci:
FrontModule
→ BasePresenter
→ ArticlePresenter
AdminModule
→ BasePresenter
→ ArticlePresenter
3. Vytvořím si knihovnu na překládání a k tomu editační presenter: MyPackage\Translator\AdminPresenter
<?php
namespace MyPackage\Translator;
class AdminPresenter extends *BaseModule\SecuredPresenter*
// do extends nevím co napsat, jakou třídu sem můžu takhle napevno dát aniž bych nutil používat aplikace jednu z výše uvedených konvencí ?
// jednou by tam mělo být BaseModule/AdminPresenter a podruhé AdminModule/BasePresenter
?>
Je to součást knihovny, kterou vždy dám do adresáře libs, takže by měla fungovat sama bez jakéliv editace zdrojových kódů
Editoval semtex.989 (14. 1. 2012 18:07)
- 22
- Člen | 1478
VYtvořil bych si třeba v namespace MyPackage SecuredPresenter, ktery
dědí od Nette\Application\UI\Presenter a pak včechny Presentery v namespace
MyPackage, které mají být zabezpečený, dědí z něj
→ extends MyPackage\SecuredPresenter
Ale moc se mi to tvoje řešení nelíbí. Proč třeba prostě nemáš jen
třeba adresář AdminModule
a do něj neskládáš
presentery/Moduly, které spadají pod administraci. Tomu Controlu je to přece
jedno, kterej Presenter si ho vytvoří.
Editoval 22 (14. 1. 2012 18:29)
- Ani
- Člen | 226
IMHO nemužeš zadrátovat něco, co se má měnit podle potřeb dané
aplikace…
Tj. buď udělat BasePresenter lépe konfigurovatelný, případně je to zralé
na inteface Secured…
Ale abych se přiznal, tak ani z detailního popisu mi moc není jasne v čem
je reálný problém (ve výsledku stejně budou věechny admin Presentery
secured, takže se ten dá vložit mezi je a BasePresenter)…
- semtex.989
- Člen | 75
@22:
Ytvořil bych si třeba v namespace MyPackage SecuredPresenter, ktery dědí od Nette\Application\UI\Presenter
To se mi právě od začátku nelíbí, protože pak nemůže transparentně dědit od BaseModule\AdminPresenter (to ješte rozeberu níže).
Ale moc se mi to tvoje řešení nelíbí.
Mně taky ne, proto nad tím přemýšlím.
Tomu Controlu je to přece jedno, kterej Presenter si ho vytvoří.
O žádném Controlu neuvažuju – místo Controlu by administraci Translatoru zajistil celkově jen MyPackage\TranslationModule\AdminPresenter.
Proč třeba prostě nemáš jen třeba adresář AdminModule a do něj neskládáš presentery/Moduly, které spadají pod administraci.
Tím naskládáním se dá myslet jen to, že zkopíruju třídu MyPackage\TranslationModule\AdminPresenter (v adesáři /libs/..) do aplikace (adresář /app/presenters/..) a přejmenuju na TranslationModule\AdminPresenter a přepíšu předka v extends – to prostě není čisté řešení
@Ani:
stejně budou věechny admin Presentery secured, takže se ten dá vložit mezi je a BasePresenter
Právě že se mezi ně nedá nic vložit. Běžný presenter v administraci bude mít např. tyto předky:
- TranslatorModule\AdminPresenter → BaseModule\AdminPresenter → Nette\Application\UI\Presenter
Presenter odvezený od MyPackage\TranslationModule\AdminPresenter bude mít tyto předky:
- TranslatorModule\AdminPresenter → MyPackage\TranslationModule\AdminPresenter ->Nette\Application\UI\Presenter
- NEDOSTANU mezi to BaseModule\AdminPresenter a to je ten průšvih
Editoval semtex.989 (15. 1. 2012 14:25)
- 22
- Člen | 1478
@semtex.989: upřímně řečeno, už nevím, co vymýšlíš. Nerozumím například tomu, proč v BaseModule nemůže mít obecný BasePresenter a SecuredPresenter. Pak přece můžu z jakéhokoliv Modulu spoléhat na jejich existenci a dědím buď z BasePresenteru nobo AdminPresenteru nebo SecuredPresenteru.
//Obecný BasePresenter všech modulů
namespace BaseModule;
abstract class BasePressenter extends Nette\Application\UI\Presenter{}
//Obecný SecuredPresenter
namespace BaseModule;
abstract class SecuredPressenter extends BasePresenter{}
//Obecný AdminPresenter všech modulů
namespace BaseModule;
abstract class AdminPressenter extends SecuredPresenter{}
//AdminPresenter z TranslationModule
namespace MyPackage\TranslationModule;
final class AdminPressenter extends BaseModule\SecuredPresenter{}
Takhle to nejde?
Editoval 22 (15. 1. 2012 14:56)
- semtex.989
- Člen | 75
To jde, ale musím spoléhat na existenci určitého BasePresenteru nebo SecuredPresenteru.
A jsou minimálně dvě konvence jak jsem psal výše: https://forum.nette.org/…e-dedicnosti#…
Asi se budu muset smířit s tím, že univerzálně to napsat nejde.
- 22
- Člen | 1478
Tak od toho máš snad ten BaseModul, aby jsi na to mohl spoléhat. Nebo ten je tam na co? To co cheš ty dědičnost spíš vylučuje. Mimochodem, spoléháš se už na Nette\Application\UI\Presenter.. co když ho nebudeš mít? Nevím, co myslíš ani slovem konvence v tomhle případě.
Editoval 22 (15. 1. 2012 15:35)
- semtex.989
- Člen | 75
Ted mně napadlo poměrně elegantní řešení:
<?php
namespace MyPackage\TranslationModule;
if(!class_exists(__NAMESPACE__ . '\InheritedPresenter'){
if(class_exists('BaseModule\AdminPresenter', TRUE)){
abstract class InheritedPresenter extends \BaseModule\AdminPresenter{}
}elseif(class_exists('AdminModule\BasePresenter', TRUE)){
abstract class InheritedPresenter extends \AdminModule\BasePresenter{}
}else{
abstract class InheritedPresenter extends \Nette\Application\UI\Presenter{}
}
}
final class AdminPressenter extends InheritedPresenter{}
?>
Takhle bude presenter z knihovny „MyPackage“ nezávislý na aplikaci (nenutí žádnou konvenci pojmenování BasePresenteru) a přinejhorším si dohledá Nette\Application\UI\Presenter
Editoval semtex.989 (15. 1. 2012 15:55)
- Filip Procházka
- Moderator | 4668
Sodoma gomora.
@**22**: +1
@**semtex.989**: NIC, kde definuješ třídu v podmínce, se nedá ani zdánlivě označit za elegantní. Vymýšlíš hlouposti. Už se na to vykašli a začni psát komponenty.
Editoval HosipLan (15. 1. 2012 16:22)
- ptacek.pavel
- Člen | 27
ehh.. Tvé řešení !== elegantní a už vůbec !== obecné (s přídomkem !important)
Takhle zadrátuješ svoji obecnou komponentu do tvé aplikace ještě víc, než kdybys v aplikaci používal obecné komponenty. Navíc, bavíš se o presenteru, který je z logiky věci zadrátován do aplikace a není jeho účelem být použitelný napříč apps!
Jestli jsem tě chytnul správně, chceš mít jeden presenter (stejný kód) např. ve 3 tvých nette aplikacích. Řešením je používat stejný návrh v těch třech aplikacích a copy/paste. Řešíš, jak udělat stejný motor pro 10 aut tak, že si podmínku zadrátuješ do stroje, který vyrábí sedačky pro spolujezdce.
Tohle je cesta do pekel.
- Patrik Votoček
- Člen | 2221
mám 100 chutí vám to tady zamknout.
vymýšlíte tady samé kraviny.
řešení padlo už tady: https://forum.nette.org/…e-dedicnosti#… detailnější vysvětlení tady https://forum.nette.org/…e-dedicnosti#….
fakt nevím co furt řešíte…