[php] Referentie naar aanroepende object krijgen.

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • cyberstalker
  • Registratie: September 2005
  • Niet online

cyberstalker

Eersteklas beunhaas

Topicstarter
In een functie heb ik een handle naar het object nodig dat de functie aanroept. m.a.w.: Als functie a uit object functie b uit object b aanroept wil ik in functie b een link hebben naar object a. Zonder dat expliciet mee te geven.

Ik maak nu gebruik van debug_backtrace(). Dit werkt goed, maar het lijkt me niet de meest ideale manier, aangezien het toch eigenlijk een debug functie is. De code die ik nu heb:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<?php

    abstract class BaseComponent
    {
        private $getters    =   array();
        private $setters    =   array();

        public function __get($name)
        {
            if (isset($this->getters[$name])) {
                $class      =   $this->getters[$name][0];
                $function   =   $this->getters[$name][1];
                return $class->$function();
            }
        }

        public function __set($name, $value)
        {
            if (isset($this->setters[$name])) {
                $class      =   $this->setters[$name][0];
                $function   =   $this->setters[$name][1];
                $class->$function($value);
            }
        }

        public function __isset($name)
        {
            return isset($this->getters[$name]);
        }

        protected function registerGetter($name, $function)
        {
            $trace      =   debug_backtrace();
            $caller     =   $trace[1]['object'];
            $function   =   array($caller, $function);

            if (is_callable($function)) {
                $this->getters[$name]   =   $function;
                return true;
            } else {
                return false;
            }
        }

        protected function registerSetter($name, $function)
        {
            $trace      =   debug_backtrace();
            $caller     =   $trace[1]['object'];
            $function   =   array($caller, $function);

            if (is_callable($function)) {
                $this->setters[$name]   =   $function;
                return true;
            } else {
                return false;
            }
        }
    }

?>


Ik heb overal gezocht, maar ik kan geen nette manier vinden om dit op te lossen. Weet iemand hoe ik dit op een degelijke manier kan aanpakken? Het gaat dus, voor de duidelijkheid, op de $caller variabele in de functies registerGetter en registerSetter

Ik ontken het bestaan van IE.


Acties:
  • 0 Henk 'm!

  • kluyze
  • Registratie: Augustus 2004
  • Niet online
Nope volgens mij is er geen andere functie die dit doet. Als je het niet zo op debug functies hebt begrepen kan je er altijd een wrapper rond maken.

Waarom kan je die waarde niet meegeven? Dat is de meest propere manier om dit te doen, eventueel kan je nog iets van een global of static propertie iets doen, of je roept eerst een andere method op waar je het object mee geeft.

Als je niet oneindig veel objecten hebt die die methode aanroepen kan je eventueel een aantal wrappers maken waar verschillende objecten andere methodes aanroepen, dan weet je welke methode gebruikt werd en kan je dus weten welk(e) object(en) die methode kennen.

[ Voor 25% gewijzigd door kluyze op 04-08-2010 22:10 ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
kluyze schreef op woensdag 04 augustus 2010 @ 22:07:
Nope volgens mij is er geen andere functie die dit doet. Als je het niet zo op debug functies hebt begrepen kan je er altijd een wrapper rond maken.
Waarmee je jezelf voor de gek houdt want je gebruikt 't dan nog steeds 8)7
kluyze schreef op woensdag 04 augustus 2010 @ 22:07:
Waarom kan je die waarde niet meegeven? Dat is de meest propere manier om dit te doen, eventueel kan je nog iets van een global of static propertie iets doen, of je roept eerst een andere method op waar je het object mee geeft.
...of gebruik een parameter in de constructor.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • kluyze
  • Registratie: Augustus 2004
  • Niet online
RobIII schreef op woensdag 04 augustus 2010 @ 22:09:
[...]

...of gebruik een parameter in de constructor.
Maar dan moet dat object telkens opnieuw aangeroepen worden, het kan ook zijn dat meerdere objecten datzelfde object mee krijgen. Dus object b wordt aangemaakt en daarna meegegeven aan object a, c, d, e, ...

En inderdaad, het is niet netjes om debug functies te gebruiken. Maar waarom eigenlijk? Omdat het niet mooi in de code staat? Als de developers van die functie het een anderen naam hadden gegeven zoals 'get_caller_object()' hadden we dan nog deze thread gehad? Of was het opeens wel interessant en toegelaten om die functie te gebruiken?

[ Voor 42% gewijzigd door kluyze op 04-08-2010 22:18 ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
kluyze schreef op woensdag 04 augustus 2010 @ 22:14:
[...]
Maar dan moet dat object telkens opnieuw aangeroepen worden, het kan ook zijn dat meerdere objecten datzelfde object mee krijgen. Dus object b wordt aangemaakt en daarna meegegeven aan object a, c, d, e, ...
En dat zijn dan keuzes die je maakt op basis van wat het handigst/best is voor je. Dus meegeven in een constructor kan net zo zinnig zijn in situatie X als meegeven in een method in situatie Y is. Wat is je punt?
Een beetje programmeur maakt een keuze a.d.h.v. kennis/ervaring; er is geen manier.
kluyze schreef op woensdag 04 augustus 2010 @ 22:14:
En inderdaad, het is niet netjes om debug functies te gebruiken. Maar waarom eigenlijk? Omdat het niet mooi in de code staat? Als de developers van die functie het een anderen naam hadden gegeven zoals 'get_caller_object()' hadden we dan nog deze thread gehad? Of was het opeens wel interessant en toegelaten om die functie te gebruiken?
Debug functies zijn meestal....debug functies. Ze unwinden de stack of halen andere ranzige kunstjes uit om bepaalde informatie boven water te halen die een functie helemaal niet zou mogen hebben. Ze zijn bedoeld om, euh, je te helpen debuggen. Ze zijn vaak niet erg performant en op het moment dat je dit soort ranzige constructies nodig hebt om bepaalde zaken boven water te krijgen moet je toch eens gaan denken of je wel de juiste ontwerpkeuzes hebt gemaakt in je model.

[ Voor 50% gewijzigd door RobIII op 04-08-2010 22:23 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • cyberstalker
  • Registratie: September 2005
  • Niet online

cyberstalker

Eersteklas beunhaas

Topicstarter
kluyze schreef op woensdag 04 augustus 2010 @ 22:14:
[...]
Maar dan moet dat object telkens opnieuw aangeroepen worden, het kan ook zijn dat meerdere objecten datzelfde object mee krijgen. Dus object b wordt aangemaakt en daarna meegegeven aan object a, c, d, e, ...

En inderdaad, het is niet netjes om debug functies te gebruiken. Maar waarom eigenlijk? Omdat het niet mooi in de code staat? Als de developers van die functie het een anderen naam hadden gegeven zoals 'get_caller_object()' hadden we dan nog deze thread gehad? Of was het opeens wel interessant en toegelaten om die functie te gebruiken?
Dat zal niet gebeuren. Zoals jullie zien zijn de functies registerGetter en registerSetter protected functies en is BaseComponent zelf een abstracte klasse.

BaseComponent wordt dus extend door andere klasses die vervolgens gebruik kunnen maken van deze functies om getters en setters te definiëren.

Nu weet ik dat PHP wel zo'n mooie parent:: functie heeft, maar de child:: functie (die ik hier dus eigenlijk nodig heb) heb ik nog niet gevonden.

Ik ontken het bestaan van IE.


Acties:
  • 0 Henk 'm!

  • kluyze
  • Registratie: Augustus 2004
  • Niet online
@RobIII; Ik wou geen punt maken, ik melde alleen dat er dan voorwaarden aan verbonden zijn. En natuurlijk heb je wel een punt ivm de debug functies, maar ik vroeg me alleen af, of developers de functies links laten liggen omdat er 'debug' instaat of omdat ze echt weten wat voor functies het zijn.

[ Voor 59% gewijzigd door kluyze op 04-08-2010 22:31 ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
kluyze schreef op woensdag 04 augustus 2010 @ 22:24:
Ik wou geen punt maken, ik melde alleen dat er dan voorwaarden aan verbonden zijn.
Er zijn altijd voorwaarden aan verbonden ;) Bij het meegeven aan een method of via een property setten gelden net zo goed voorwaarden.

[ Voor 15% gewijzigd door RobIII op 04-08-2010 22:25 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • pderaaij
  • Registratie: Oktober 2005
  • Laatst online: 18-08 20:16
cyberstalker schreef op woensdag 04 augustus 2010 @ 22:22:
[...]

Dat zal niet gebeuren. Zoals jullie zien zijn de functies registerGetter en registerSetter protected functies en is BaseComponent zelf een abstracte klasse.

BaseComponent wordt dus extend door andere klasses die vervolgens gebruik kunnen maken van deze functies om getters en setters te definiëren.

Nu weet ik dat PHP wel zo'n mooie parent:: functie heeft, maar de child:: functie (die ik hier dus eigenlijk nodig heb) heb ik nog niet gevonden.
Als ik het goed begrijp wil je altijd functies aanroepen die uit een extended class van BaseComponent komt. Volgens mij kun je dan ook met een automagische __call functie werken. In combinatie met een call_user_func(_array) moet het volgens mij lukken zonder Reflectie of backtrace.

Al naar gekeken toevallig?

Acties:
  • 0 Henk 'm!

  • CoolGamer
  • Registratie: Mei 2005
  • Laatst online: 14:29

CoolGamer

What is it? Dragons?

cyberstalker schreef op woensdag 04 augustus 2010 @ 22:22:
Dat zal niet gebeuren. Zoals jullie zien zijn de functies registerGetter en registerSetter protected functies en is BaseComponent zelf een abstracte klasse.

BaseComponent wordt dus extend door andere klasses die vervolgens gebruik kunnen maken van deze functies om getters en setters te definiëren.

Nu weet ik dat PHP wel zo'n mooie parent:: functie heeft, maar de child:: functie (die ik hier dus eigenlijk nodig heb) heb ik nog niet gevonden.
Ik denk dat je te moeilijk aan het denken bent. Zodra je overerft kan je gewoon $this vanuit je super-class gebruiken om functies aan te roepen van de child-class.

¸.·´¯`·.¸.·´¯`·.¸><(((º>¸.·´¯`·.¸><(((º>¸.·´¯`·.¸.·´¯`·.¸.·´¯`·.¸<º)))><¸.·´¯`·.¸.·´¯`·.¸.·´¯`·.¸


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:53

MueR

Admin Tweakers Discord

is niet lief

TheCoolGamer schreef op woensdag 04 augustus 2010 @ 23:47:
[...]

Ik denk dat je te moeilijk aan het denken bent. Zodra je overerft kan je gewoon $this vanuit je super-class gebruiken om functies aan te roepen van de child-class.
Nee, dat kan alleen wanneer je een class extend. Niet wanneer class A een class B terugstuurt.

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • pderaaij
  • Registratie: Oktober 2005
  • Laatst online: 18-08 20:16
TheCoolGamer schreef op woensdag 04 augustus 2010 @ 23:47:
[...]

Ik denk dat je te moeilijk aan het denken bent. Zodra je overerft kan je gewoon $this vanuit je super-class gebruiken om functies aan te roepen van de child-class.
Dat kan wanneer je de functie als abstract hebt gedefinieerd.

PHP:
1
2
3
4
5
6
7
class A {
 abstract function hello() { }
}

class B extends A {
 function hello() { echo 'Hello world!'; }
}

Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:53

MueR

Admin Tweakers Discord

is niet lief

Dat is ook niet helemaal correct. Een abstracte functie is bedoeld om overschreven te worden in een extended class. Dat wil niet zeggen dat je niet-abstracte functies niet ook gewoon kan overschrijven.
PHP:
1
2
3
4
5
6
7
8
9
10
11
class A {
  public function Foo() {
    echo 'Hallo';
  }
}
class B extends A {
  public function Foo($name) {
    parent::Foo();
    echo ' '.$name; // echoes: Hello $name
  }
}

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • pderaaij
  • Registratie: Oktober 2005
  • Laatst online: 18-08 20:16
MueR schreef op donderdag 05 augustus 2010 @ 10:22:
Dat is ook niet helemaal correct. Een abstracte functie is bedoeld om overschreven te worden in een extended class. Dat wil niet zeggen dat je niet-abstracte functies niet ook gewoon kan overschrijven.
PHP:
1
2
3
4
5
6
7
8
9
10
11
class A {
  public function Foo() {
    echo 'Hallo';
  }
}
class B extends A {
  public function Foo($name) {
    parent::Foo();
    echo ' '.$name; // echoes: Hello $name
  }
}
Maar een functie die niet gedefinieerd is in de parent, al dan niet abstract, kun je vanuit de parent niet benaderen met $this. Of vergis ik me nu?

Acties:
  • 0 Henk 'm!

  • Hipska
  • Registratie: Mei 2008
  • Laatst online: 15-09 21:08
Bedoel je nu dit?
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

class A {
    public function Foo(){
        echo 'Foo';
        $this->Bar();
    }
}


class B {
    public function Bar(){
        echo 'Bar';
    }
}

$b = new B();
$b->Foo();

?>


Op het moment dat je new B doet bestaat de method $this->Bar(); toch? Een instantie van A zal fouten geven wanneer je $a->Foo(); doet.

[ Voor 0% gewijzigd door Hipska op 05-08-2010 10:38 . Reden: code markup ]


Acties:
  • 0 Henk 'm!

  • CoolGamer
  • Registratie: Mei 2005
  • Laatst online: 14:29

CoolGamer

What is it? Dragons?

MueR schreef op donderdag 05 augustus 2010 @ 00:35:
[...]

Nee, dat kan alleen wanneer je een class extend.
Dat is toch ook wat hier gebeurd? Het gaat om een abstracte class, waarbij de TS de class zoekt die de protected functions aanroept. Dat is dus gewoon altijd $this.

¸.·´¯`·.¸.·´¯`·.¸><(((º>¸.·´¯`·.¸><(((º>¸.·´¯`·.¸.·´¯`·.¸.·´¯`·.¸<º)))><¸.·´¯`·.¸.·´¯`·.¸.·´¯`·.¸


Acties:
  • 0 Henk 'm!

  • pderaaij
  • Registratie: Oktober 2005
  • Laatst online: 18-08 20:16
Ik bedoel dit

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php 

class A { 
    public function Foo(){ 
        echo 'Foo'; 
        $this->Bar(); 
    } 

    public function callChild() {
        $this->Bar();
    }
} 


class B extends A { 
    public function Bar(){ 
        echo 'Bar'; 
    } 
} 


$b = new B(); 
$b->Bar();   // Output 'Bar'
$b->Foo();  // Output 'Foo'
$b->callChild(); // Fatal error lijkt me?

?>


[EDIT]

Output in 5.3.3
BarFooBarBar

Niet dus... Je kan dus met $this een onbekende child functie uit de parent aanroepen. TS zou dan het beste met call_user_func_array kunnen werken.

[ Voor 18% gewijzigd door pderaaij op 05-08-2010 10:45 ]


Acties:
  • 0 Henk 'm!

  • Hipska
  • Registratie: Mei 2008
  • Laatst online: 15-09 21:08
@pderaaij: Waarom geeft volgens jou $b->Foo(); dan niet een Fatal error net als bij callChild?

Volgens mij zal de output in deze volgorde zijn:
Bar
FooBar
Bar

Fatal error of iets dergelijks krijg je bij $a->Foo(); en $a->callChild();

EDIT: Je zag het zelf ook al. Je moet denken dat de functies van A allemaal in B komen te staan wanneer je extend doet. Wanneer je dat in je hoofd ook zo ziet, zal je plots merken dat die output compleet logisch en normaal is. Lijkt me toch gewoon basis OOP?

[ Voor 35% gewijzigd door Hipska op 05-08-2010 10:49 ]


Acties:
  • 0 Henk 'm!

  • pderaaij
  • Registratie: Oktober 2005
  • Laatst online: 18-08 20:16
Hipska schreef op donderdag 05 augustus 2010 @ 10:48:
EDIT: Je zag het zelf ook al. Je moet denken dat de functies van A allemaal in B komen te staan wanneer je extend doet. Wanneer je dat in je hoofd ook zo ziet, zal je plots merken dat die output compleet logisch en normaal is. Lijkt me toch gewoon basis OOP?
Van A naar B is inderdaad logisch, maar B naar A vind ik minder logisch en vind ik ook niet echt goed OOP pardigm. Een parent mag in principe toch niet vertrouwen op child functies?

Acties:
  • 0 Henk 'm!

  • Hipska
  • Registratie: Mei 2008
  • Laatst online: 15-09 21:08
Nee in principe niet, maar niets houdt iemand tegen om het wel te doen. Bijvoorbeeld als A een abstract class is dan maakt het al wat meer nuttig/aanvaardbaar.

Ik ben zeker ook van mening dat deze manier niet echt 'proper' is en dat de TS eens kan kijken naar de opbouw van zijn classes en objecten. Ik denk dat er betere wegen zijn die ook naar Rome kunnen leiden.

[ Voor 1% gewijzigd door Hipska op 05-08-2010 10:59 . Reden: verduidelijking ]


Acties:
  • 0 Henk 'm!

  • pderaaij
  • Registratie: Oktober 2005
  • Laatst online: 18-08 20:16
Ik dacht dat het in PHP was uitgeschakeld en dat daardoor deze constructie niet mogelijk was. Besef alleen net dat, dat ging over multiple inheritance.

Weer wat geleerd :)

Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:53

MueR

Admin Tweakers Discord

is niet lief

TheCoolGamer schreef op donderdag 05 augustus 2010 @ 10:43:
[...]

Dat is toch ook wat hier gebeurd? Het gaat om een abstracte class, waarbij de TS de class zoekt die de protected functions aanroept. Dat is dus gewoon altijd $this.
Nee. Tenminste, dat maak ik niet op uit de TS. Hij wil een aantal verschillende, losstaande classes, die dan wel allemaal extenden vanaf een basis class, aan kunnen roepen volgens mij. Dat gaat je alleen nooit lukken zonder daadwerkelijke referentie aan het object als argument in een functie mee te geven.

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • cyberstalker
  • Registratie: September 2005
  • Niet online

cyberstalker

Eersteklas beunhaas

Topicstarter
MueR schreef op donderdag 05 augustus 2010 @ 11:52:
[...]

Nee. Tenminste, dat maak ik niet op uit de TS. Hij wil een aantal verschillende, losstaande classes, die dan wel allemaal extenden vanaf een basis class, aan kunnen roepen volgens mij. Dat gaat je alleen nooit lukken zonder daadwerkelijke referentie aan het object als argument in een functie mee te geven.
Ik had gehoopt dat er een mooie manier was om het object van waaruit de functie aangeroepen wordt te verkrijgen. Ik denk dat ik nu maar een apart initialize() functie maak in mijn base class en die ik $this meegeef als parameter en vervolgens deze referentie opslaat.

Bedankt voor de hulp iedereen :) .

Ik ontken het bestaan van IE.


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Als alles via een soort god object in elkaar moet grijpen heb je doorgaans een suboptimaal ontwerp. ;)

{signature}


Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Voutloos schreef op donderdag 05 augustus 2010 @ 20:43:
Als alles via een soort god object in elkaar moet grijpen heb je doorgaans een suboptimaal ontwerp. ;)
God class in dezen, waarschijnlijk te gebruiken in een ORM of iets dergelijks. Hiermee kun je 'at runtime' getters / setters definiëren.

Oké, het voegt verder niks toe aan het geheel anders dan overbodige compleiteit, maar toch. Even correct zijn in dezen ;).

Acties:
  • 0 Henk 'm!

  • r0bert
  • Registratie: September 2001
  • Laatst online: 30-07 02:32
Begin vanaf scratch en kies een andere approach of kies een totaal andere taal. De code in de topicstart gaat je van het ene in het andere probleem helpen. Ik neem aan dat je gewoon een (dynamic) proxy pattern wilt?

[ Voor 16% gewijzigd door r0bert op 05-08-2010 22:12 ]

Pagina: 1