Předek presenteru bez vícenásobné dědičnosti

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

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?

Filip Procházka
Moderator | 4668
+
0
-

Cca takto

MyPresenter extends AdminPresenter extends BasePresenter
semtex.989
Člen | 75
+
0
-

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
?>
Nox
Člen | 378
+
0
-

Ano, tak

semtex.989
Člen | 75
+
0
-

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)

Aurielle
Člen | 1281
+
0
-

Co ti brání vytvořit si MyPackage\Translator\AdminPresenter, a další presentery dědit od něj? Nebo jsem nepochopil otázku…

semtex.989
Člen | 75
+
0
-

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

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

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

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

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>

22
Člen | 1478
+
0
-

@semtex.989: jak nemá view? Můžeš mít render metod pro komponentu, kolik chceš..

semtex.989
Člen | 75
+
0
-

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

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

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

Aurielle
Člen | 1281
+
0
-

Pleteš jabka a hrušky. Komponenta nemá viewy.

semtex.989
Člen | 75
+
0
-

Dobře, tak řekněme metoda renderXyz co emuluje view..

Patrik Votoček
Člen | 2221
+
0
-

gmvasek napsal(a):

Pleteš jabka a hrušky. Komponenta nemá viewy.

bullshit… má akorát z principu fungují jinak než v presenteru

22
Člen | 1478
+
0
-

semtex.989: Pravděpodobně špatný návrh.. to co děláš, je typický modul imho

semtex.989
Člen | 75
+
0
-

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

22
Člen | 1478
+
0
-

K tomu by měl existovat nějaký SecuredPresenter, který ve startupu ověří uživatele a od toho pak dědí ostatbí presentery v administraci.

semtex.989
Člen | 75
+
0
-

@22: Přesně tak. A teď jde o to, jak zajistit aby TranslationModule/AdminPresenter měl předka SecuredPresenter.

22
Člen | 1478
+
0
-

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

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

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

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)

22
Člen | 1478
+
0
-

a z čeho ti ten preseneter dědí normálně, pokud by neexistoval Secured? Nějak tomu už nerozumím asi.

Editoval 22 (14. 1. 2012 17:37)

semtex.989
Člen | 75
+
0
-

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

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

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

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

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

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

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

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

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

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

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…

semtex.989
Člen | 75
+
0
-

@ptacek.pavel: diky za vymluvení, to jsem chtěl „slyšet“!