[PHP] call_user_func en $this

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • TheNephilim
  • Registratie: September 2005
  • Laatst online: 12:20
Bij het 'dynamisch' laden van een method uit een class, gaat er iets niet goed met het gebruiken van $this. Nu gebruik ik call_user_func in een class, om een andere class aan te roepen met een bepaalde method. Hieronder een heel simpel voorbeeld van wat ik doe. Het onderstaande zorgt voor deze error: Using $this when not in object context...

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
class ClassA {

    function methodA {

        return call_user_func(array('ClassB', 'ClassBMethodA'));

    }
}

class ClassB extends ClassA {
    
    private $ID;
    
    function __construct () {
        
        $this->ID = $this->get_ID();

    }
    
    function MethodA () {
        
        echo $this->ID;
        
    }
}

new ClassA();


Nu is er op internet het een en ander te vinden over deze error, maar ik vraag me af waar hier nu precies het probleem zit. Wellicht beter gezegd, kan iemand uitleggen wat het probleem is; de context (class in class) of de call_user_func?

Wat de bedoeling is? Op basis van een string een controller inladen die iets voor mij doet. Dus één algemene class met de basis handelingen en een andere class die er iets aan toevoegd op basis van de request. Zie het als fruit waarbij appel de eerste de basis is en de tweede gedetailleerder is.

Wellicht zijn er betere manieren, maar dit is waar ik mee op de proppen gekomen ben.

---

Edit: Ik heb een oplossing gevonden in de volgende methode: http://rabaix.net/en/arti...s-with-dynamic-parameters

[ Voor 5% gewijzigd door TheNephilim op 18-03-2013 20:24 ]


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 04-07 15:03

NMe

Quia Ego Sic Dico.

Je roept niet $this->ClassBMethodA() aan maar ClassB::ClassBMethodA(). Je hebt $this dus niet tot je beschikking omdat je niet opereert op het object maar op de class. Om diezelfde reden heb je je member $ID niet beschikbaar. Heeft verder overigens weinig te maken met het feit dat je call_user_func gebruikt, al zet ik ook zo mijn vraagtekens bij het nut daarvan in dit geval.

Sowieso is het een beetje vreemd ontwerp om in je baseclass je afgeleide class aan te roepen. Dat voelt een beetje als een voertuigklasse waarin je bewerkingen gaat doen die alleen van toepassing kunnen zijn op een auto.

[ Voor 21% gewijzigd door NMe op 18-03-2013 20:26 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • TheNephilim
  • Registratie: September 2005
  • Laatst online: 12:20
Check de zojuist door mij geplaatste edit, maar daarnaast... Dat het niet de beste oplossing is, daar was ik al een beetje bang voor. Om nog eens duidelijk te maken wat de bedoeling is:

Ik heb een plugin binnen Wordpress die moet reageren op bepaalde requests, een soort API dus. Het omvat en API met was basis functies en daarnaast een aantal functies voor een bepaalde request. Sommige functies uit de basis klasse zijn toepasbaar voor iedere request, dus had ik bedacht een hoofd klasse te maken voor alle algemene dingen en enkele extra klassen voor de requests.

Eigenlijk is het zelfs de bedoeling dat ik dynamisch extra klassen toe kan voegen voor verschillende requests. Kortom (bijv.); A = de plugin en B en C bevatten extra methodes. Ik wil graag D E F G kunnen toevoegen zonder aanpassingen te doen aan A.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 04-07 15:03

NMe

Quia Ego Sic Dico.

Zonder verder de details te kennen klinkt dat alsof je klassen wil gebruiken voor de verkeerde dingen. Een klasse staat voor een entiteit. Wat jij omschrijft is een toepassing waarin je een klasse per pagina op je site hebt. Dat kan op zich best, dan heb je een class BasePage en een class ContactPage bijvoorbeeld, maar doorgaans heb je dan gewoon een (abstracte) class die de methods bepaalt en een afgeleide class die de logica voor die methods specificeert. Bijvoorbeeld:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
abstract class BasePage {
    abstract public function render();

    protected function debug() {
        echo $this->debugInfo;
    }
}

class ContactPage extends BasePage {
    public function render() {
         // contactformulier afdrukken
    }
}


$contact = new ContactPage();
$contact->render();
$contact->debug();

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • TheNephilim
  • Registratie: September 2005
  • Laatst online: 12:20
Om dan toch even wat gedetailleerder op het onderwerp in te gaan: Het betreft een API aan de 'server' kant, die in eerste instantie een 'heartbeat' ontvangt van een client. Naast een heartbeat, kan het ook een andere actie zijn. Bijvoorbeeld de server die de client vraagt om versie gegevens en de client die erop reageert.

Mijn doel was om een algemene Class te maken waaraan gemakkelijk extra Actions aan toegevoegd worden. Dus naast Heartbeat en GetVersion zou er dan bijvoorbeeld GetSomething bij komen.

Als ik je goed begrijp is dit dus niet dé manier om dit te doen. Ik had eigenlijk ook iets cleaners voor ogen, maar gaandeweg kom je erachter dat er toch meer dingen benodigd zijn om het zooitje te laten werken.

Ik ga er nog eens over nadenken hoe ik het beter kan oplossen, bedankt voor je input! :D

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 04-07 15:03

NMe

Quia Ego Sic Dico.

Klinkt eerder alsof je een manager class wil hebben die een lijst met objecten bijhoudt die allemaal instanties zijn van (afgeleiden van) een Action-class. Dan is het een kwestie van een ActionManager maken en daar Actions aan toe te voegen zoveel je nodig hebt en bij je uitvoerfase doe je $actionManager->run() die weer één voor één $action->run() aanroept.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • TheNephilim
  • Registratie: September 2005
  • Laatst online: 12:20
Dat klinkt nog ingewikkelder dan wat ik eigenlijk wilde! :+ Wat betreft je opmerking over dingen aan elkaar knopen zonder dat ze betrekking op elkaar hebben heb ik wel wat mee gedaan. Hieronder een simpel voorbeeld van hoe het nu werkt met aanroep naar /api/heartbeat

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
class Plugin {
    function __contruct () {

        // Luisteren naar inkomende requests
        add_action('parse_request', array($this, 'parse_request'));

        // Meer Wordpress hooks
    }

    // Meer functies die aansluiten op hooks

    // Functie om iets te doen met een ingekomen request, alleen API requests
    function parse_request(&$wp) {

        // API Actie => Controller
        $controllers = array(
            'heartbeat' => 'Controller_Heartbeat'
        );

        // Check of de actie bekend is
        if (array_key_exists($action, $controllers)) {

            switch ($action) {

                case 'heartbeat':

                    $heartbeat = new Controller_Heartbeat();

                    $heartbeat->API();

                    break;
                }

            } else {
                // Error, actie bestaat niet
            }
        }
    }
}

class Client {
    // Client opzoeken/aanmaken/etc
}

class Controller_Heartbeat {
    
    function __construct () {
        
        // Nieuwe client instance
        $client = new Client();
        
        // Client ID ophalen client die request uitvoerde naar de API
        $this->client_ID = $client->get_client_ID();
    }
    
    function API () {
        // Heartbeat dingen doen
    }
}


Straks komt daar wellicht bij: /api/plugins (lijst opsturen van alle plugins) of /api/plugins/update (alle plugins updaten).

Acties:
  • 0 Henk 'm!

  • Douweegbertje
  • Registratie: Mei 2008
  • Laatst online: 06-07 04:44

Douweegbertje

Wat kinderachtig.. godverdomme

hm ik ben toevallig ook een beetje bezig met een API.
Maar even voordat ik begin, het is __construct (zie lijn 2), weet niet of je dit live hebt staan tho :p

Wat ik een beetje apart vind (maar dat kan ik ook persoonlijk zijn) is dat je met classes gaat gooien.
Waarom is 'Controller_Heartbeat' een class?

Even mijn redenatie zoals ik je code lees (en voorspel hoe je hem uiteindelijk wilt maken):

In feite maak je een plugin class aan, waarin je van alles doet en daar weer per 'call' een specifieke class aanmaakt. Die je dan weer gebruikt in je plugin class, en daar roep je weer functies aan in je nieuwe 'call' class.

code:
1
2
3
4
5
6
7
case 'heartbeat': 

                    $heartbeat = new Controller_Heartbeat(); 

                    $heartbeat->API(); 

                    break;


Ik ben niet zo'n fan van cases waarin je allerlei dingen gaat doen. Roep gewoon een $this->function() aan.


Begin je plugin class gewoon met een goede constructor.
Kijk wat er wordt aangeroepen, verwerk de methode (GET, POST, w/e), verwerk de URL (api/heartbeat/init , api/heartbeat/doedit/datzuszo) en initier bijvoorbeeld al de $client = new Client();

Vervolgens kun je dan (en misschien wordt ik nu duidelijker :P ) het volgende doen:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Api()

$request = new api('http://sitemetjeapi/api/heartbeat/init'); 
if($request->ping()) //wat dus een function is in de class api
{
    $request->pong();
} 


// terwijl je dan ook verder kunt gaan met dingen zoals:

$update = new api('http://sitemetjeapi/api/plugins/update/2')
$update->doUpdate();

// of

$getUpdate = new api('http://sitemetjeapi/api/plugins/get/2')
$getUpdate->getUpdate();


Je probeert te veel zelf af te handelen in je plugin class, waarbij je (nog) weinig doet met gewoon api calls. Daarnaast is het niet erg, en zelfs goed om bijv. een Client/user class te hebben, maar een onderdeel van de api (heartbeat) zou gewoon een functie van de plugin class ''moeten' zijn.
Vooral als je heartbeat class alleen, of zo goed als bestaat uit een function API() die door je plugin class wordt aangesproken.
Pagina: 1