RobRobson: Funktionen hijacken und verändern

Hallo Forumsteilnehmer,

ich selber bin ja eher der prozedurale Programmierer (weils doch so schön schnell geht wenn man ne Idee hat ;)).
Aber theoretisch hab ich  6 Jahre OOP mitgelernt. Und da ich schon immer auf OOP umsteigen wollte, es aber nie getan hab, kommt jetzt endlich der nötige Druck von aussen.

Ich muss fremde Funktionen/Klassen für mich nutzen. Und zwar soll ich 2 Wordpressplugins ausführen und deren Ergebnisse wieder zurück in WP schreiben. Die Plugins sind aber nicht so konzipiert das sie ihre Daten auch nach aussen zur Verfügung stellen. Also müssen sie modifiziert werden das sie das jetzt tun.
Konkret muss eigentlich nur in der Hauptfunktion am Ende statt "return; " dann "return $newid;" stehen.

Klar könnte ich das auch shnell selber so hardcoden, aber da es für den unabhängigen Produktiveinsatz gedacht ist soll es auch dann noch laufen wenn die Plugins mal upgedatet werden. Sprich es muss zur Laufzeit geändert werden.

Jetzt die Frage:
Wie lösst das der der schlaue OOP Programmierer?
Meine Recherche brachte die Schlagworte Entwurfsmuster/dekorator hervor. Doch bevor ich jetzt die kommende Nacht umsonst dafür opfere wollt ich mal nachfragen ob die methode richtig ist oder ob mans anders machen sollte (wenn ja, wie?).

Vielen Dank und viele Grüße,
Rob

  1. hi,

    Wie lösst das der der schlaue OOP Programmierer?

    Naja, ich bin eher ein Praktiker und habe von PHP OOP nicht viel Ahnung. Möglicherweise funktioniert es aber auch in PHP so, wie ich das in Perl machen würde:

    Aufgabenstellung ist, wenn ich richtig verstanden habe: In der Instanz verborgene Attribute sollen außerhalb der Klasse verfügbar sein. D.h., ich brauche zusätzliche Methoden und wenn ich die nicht in die Original-Library schreiben will, erstelle ich einfach eine neue Datei und behaupte am Anfang der Datei, dass die zum Namespace der Original-Library gehört. Beispiel:

      
    # im main-Script  
    use Foo; # das ist die Original-Library  
      
    # erstelle eine neue Datei FooPlus.pm und schreibe in die erste Zeile  
    package Foo;  
      
    # und im Weiteren definiere ich in FooPlus.pm meine Methoden...  
      
    # Eine Zeile muss jedoch in die Original-Lib geschrieben werden:  
    use FooPlus;  
    
    

    Hotti

  2. Hi Rob,

    ein Beispiel wäre folgendes:

    class beispiel  
    {  
       function calcZahl()  
       {  
           $intZahl = 2 + 2;  
           return;  
       }  
    }  
    
    

    Du möchtest jetzt $intZahl zurück liefern, da du darauf zugreifen möchtest?
    Die Frage ist jetzt wie $intZahl implementiert ist.

    • Wenn es eine public Variable ist kannst du ja einfach drauf zu greifen. Wäre zwar keine Saubere Lösung aber schnell und pragmatisch.

    • Wenn es eine protected Variable ist, kann du eine Unterklasse definieren und eine Methode einführen um an $intZahl zu kommen.

      
    class unterklasse extends beispiel  
    {  
       function getZahl()  
       {  
           return $this->intZahl;  
       }  
    }  
    
    

    Das Beispiel wäre auch für die Public Variante denkbar

    • Wenn die Variable private ist oder nur innerhalb der Methode existiert fällt mir keine andere Lösung ein, als die Klasse beispiel zu modifizieren. Aber das möchtest du ja nicht. Deshalb deklariert man die Variablen als private, damit man da eben von außen nicht ran kommt.

    Eventuell kannst du eine Lösung hinpfuschen in dem du über die Reflection Class von PHP gehst http://de3.php.net/manual/de/book.reflection.php

    Gruß
    T-Rex

    1. Moin T-Rex,

      Hi Rob,

      • Wenn es eine protected Variable ist, kann du eine Unterklasse definieren und eine Methode einführen um an $intZahl zu kommen.

      class unterklasse extends beispiel
      {
         function getZahl()
         {
             return $this->intZahl;
         }
      }

      
      > Das Beispiel wäre auch für die Public Variante denkbar  
        
      Ja, so ungefär hab ich mir das auch vorgestellt (nur das ich die OOP Syntax dafür nicht kannte :D).  
        
      Die Variable die ich haben will ist eigentlich garnicht groß deklariert, sie wird in der Funktion nur kurz erzeugt, an eine andere Funktion übergeben und dann nicht weiterverwendet.Ist sie dann nur innerhalb der Funktion gültig?  
        
      Und könnte mal sie nachträglich public, und damit für mich nutzbar, machen? Sprich wenn sie im Orginal nicht ausserhalb der Funktion deklariert wurde, der Funktion (über Deine extends Klasse) einfach ein "public intZahl;" voranstellen?  
        
      Viele Grüße und Danke (auch an Hotti natürlich!),  
      Rob
      
      1. Also wenn die Variable nur innerhalb der Funktion existiert dann hast du keine Chance da ran zu kommen. Weder von Außerhalb noch von einer Ober oder Unterklasse. Du kannst die Variable auch nicht einfach mal eben public deklarieren.
        1. $intZahl = 10;
        ist eine andere Variable als
        2. $this->intZahl = 10;

        1. wäre die Variable die innerhalb der Funktion existiert
        2. Ist die Objekteigenschaft (welche public, protected oder private sein kann)

        Also in deinem speziellen Fall hilft dir die OOP nicht weiter. Du musst die Funktionen ändern.

        Gruß
        T-Rex

      2. hi,

        Viele Grüße und Danke (auch an Hotti natürlich!),

        Der liest natürlich mit ;)

        Die Variable die ich haben will ist eigentlich garnicht groß deklariert, sie wird in der Funktion nur kurz erzeugt, an eine andere Funktion übergeben und dann nicht weiterverwendet.Ist sie dann nur innerhalb der Funktion gültig?

        Die Variable stirbt, wenn sie nicht weiter verwendet wird, d.h., wenn es im Laufe des Scripts keine Referenz mehr darauf gibt. Was jedoch weiterlebt bis zum Destructor (Scriptende) ist die Instanz der Klasse (das Objekt).

        Jetzt könnten wir eine Variable, die bis zum Schluss gebraucht wird, einfach als Attribut an die Klasseninstanz hängen, was jedoch einen Eingriff in den Code erfordert (und bei einem Update wieder plattgemacht würde). Wäre jedoch ne Überlegung wert.

        Vielleicht gibt es aber auch eine Möglichkeit, den gesuchten Wert aus 'anderen' Variablen, die bis jetzt bereits im Objekt enthalten sind (Attribute), zu erzeugen oder zu ermitteln. Dafür würde ich eine Subklasse bauen, womit die Attribute geerbt werden.

        Hotti

        1. Moin!

          Die Variable stirbt, wenn sie nicht weiter verwendet wird, d.h., wenn es im Laufe des Scripts keine Referenz mehr darauf gibt. Was jedoch weiterlebt bis zum Destructor (Scriptende) ist die Instanz der Klasse (das Objekt).

          Das ist nicht korrekt.

          Deine Antwort impliziert, es gäbe "den Großen Destruktor", der die Klasseninstanzen ins Jenseits befördert. Stimmt ja nicht, der Destruktor ist eine Funktion, die das Objekt ausführt, bevor es gelöscht wird.

          Zweite Implikation: Der Destruktor tritt am Skriptende auf. Stimmt auch nicht, der wird immer dann aufgerufen, wenn ein Objekt gelöscht wird. Am Skriptende natürlich spätestens, aber gern auch früher.

          Dritte Implikation deiner Antwort: Objekte leben bis zum Skriptende. Stimmt halt auch nicht, aus oben genannten Gründen.

          Jetzt könnten wir eine Variable, die bis zum Schluss gebraucht wird, einfach als Attribut an die Klasseninstanz hängen, was jedoch einen Eingriff in den Code erfordert (und bei einem Update wieder plattgemacht würde). Wäre jedoch ne Überlegung wert.

          Wäre einfach und wurde ausgeschlossen.

          Vielleicht gibt es aber auch eine Möglichkeit, den gesuchten Wert aus 'anderen' Variablen, die bis jetzt bereits im Objekt enthalten sind (Attribute), zu erzeugen oder zu ermitteln. Dafür würde ich eine Subklasse bauen, womit die Attribute geerbt werden.

          Lokale Variablen einer Funktion kann man von außen nicht erreichen, nicht mal mit Reflection.

          - Sven Rautenberg

          1. Moin Sven;

            Deine Antwort impliziert, es gäbe "den Großen Destruktor", der die Klasseninstanzen ins Jenseits befördert. Stimmt ja nicht, der Destruktor ist eine Funktion, die das Objekt ausführt, bevor es gelöscht wird.

            The REAPER. Es gibt ihn, der haut uns alle mal weg, irgendwann....

            Vielleicht gibt es aber auch eine Möglichkeit, den gesuchten Wert aus 'anderen' Variablen, die bis jetzt bereits im Objekt enthalten sind (Attribute), zu erzeugen oder zu ermitteln. Dafür würde ich eine Subklasse bauen, womit die Attribute geerbt werden.

            Lokale Variablen einer Funktion kann man von außen nicht erreichen, nicht mal mit Reflection.

            Das ist richtig. Was ich meinte: Du kannst Die Attribute eines Objekts erreichen, Attribute, z.B. die Scalare sind. Dazu musst Du das Objekt jedoch schon gut kennen: wir machen einen var_dump und sehen z.B. (Perl):

              
            $obj = {  
              FOO => 33,  
              Bar => 55,  
            };  
            
            

            was uns sonst verborgen bleibt. Jetzt hat Horst Schlauberger herausbekommen, dass sich die gesuchte Veriable infolge einfacher Addition der Attribute FOO und BAR ergibt, also 88, wenn ich richtig gerechnet habe für diesen Fall. Das meinte ich ;)

            Schöne Grüße,
            Hotti

            --
            Heute haben unsere Ameisen gelbe Füße. Meine Frau hat die Terasse gestrichen.
      3. Hi,

        Die Variable die ich haben will ist eigentlich garnicht groß deklariert, sie wird in der Funktion nur kurz erzeugt, an eine andere Funktion übergeben und dann nicht weiterverwendet.Ist sie dann nur innerhalb der Funktion gültig?

        Als Funktions-lokale Variable: Ja.
        (Das sollte aber auch der prozedurale Programmierer eigentlich schon wissen.)

        Und könnte mal sie nachträglich public, und damit für mich nutzbar, machen? Sprich wenn sie im Orginal nicht ausserhalb der Funktion deklariert wurde, der Funktion (über Deine extends Klasse) einfach ein "public intZahl;" voranstellen?

        Nicht, ohne (auch) die Methode anzupassen - so lange du in der nämlich die Syntax zum Zugriff auf die Eigenschaft nicht anpasst, wird sie weiterhin ihre lokale Variable verwenden.

        („Auch“ deswegen in Klammern, weil die explizite Deklaration der Eigenschaft als public in der Klasse nicht unbedingt erforderlich ist. Ohne diese wird eine Member-Variable bei der ersten schreibenden Verwendung automatisch implizit mit der Sichtbarkeit public angelegt. Besonders sauberer „Stil“ ist das natürlich nicht, aber für den Sonderfall wäre es ggf. akzeptabel.)

        Nebenwirkungen *könnte* das natürlich auch haben - allerdings wären die eher in dem Fall zu erwarten, wo es das public member bereits gibt (von anderen Methoden genutzt), und man dann in der in Frage stehenden Methode von der lokalen Variablen auf die Nutzung dieses Members umsteigt. Dann beeinflusst man nämlich plötzlich in dieser Werte, die auch an anderen Stellen genutzt werden.

        Dich erst mal selber etwas mehr mit den Grundlagen von OOP allgemein und OOP in PHP 5 im speziellen zu beschäftigen, wäre wohl angebracht, wenn du jetzt vor dieser Aufgabe stehst.

        MfG ChrisB

        --
        RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?