2009-06-11 7 views
6

Ich habe einen ganz besonderen Fall, in dem ich eine geschützte Methode von außerhalb einer Klasse aufrufen muss. Ich bin sehr bewusst über das, was ich programmtechnisch mache, aber ich wäre nicht völlig dagegen, dies in diesem speziellen Fall zu tun. In allen anderen Fällen muss ich weiterhin den Zugriff auf die interne Methode verweigern, und deshalb möchte ich die Methode geschützt halten.Rufen Sie eine geschützte Methode von außerhalb einer Klasse in PHP

Was sind einige elegante Möglichkeiten, auf eine geschützte Methode außerhalb einer Klasse zuzugreifen? Bisher habe ich this gefunden.

ich es annehmen, möglich sein kann, eine Art Doppelagent Instanz der Zielklasse erstellen, die sneakily Zugriff auf die Interna bieten würde ...

+0

Der beste Weg, es zu tun? Ändern Sie die Funktion zu öffentlich. – Powerlord

Antwort

0

Ich werfe dies nur da draußen, da ich nicht haben in PHP in zwei Jahren programmiert. Könnten Sie der Klasse, die die geschützte Methode aufruft, einfach eine Funktion hinzufügen?

$obj->publicFunc = create_function('$arg', 'return $this->protectedFunc($arg);'); 

bearbeiten: denke ich, Tom korrekt ist in der Dokumentation zu create_function in suchen. Es sieht so aus, als ob der Umfang von $ "falsch" ist, wenn Sie versuchen, es mit diesem Beispiel aufzurufen.


Es ist wie traditionelle anonyme Funktionen sieht, da PHP 5.3.0 ebenfalls unterstützt (und meine erste Lösung wird wahrscheinlich nicht funktionieren), also würde ich es wahrscheinlich so schreiben statt:

$obj->publicFunc = function($arg) { 
    return $this->protectedFunc($arg); 
}; 

Da ich denke, es sieht ein wenig sauberer (und Ihre IDE der Wahl wird es natürlich besser hervorheben).


Ugh, versuchte ich Reflection mit der Methode zu nennen, aber PHP wird nicht zulassen, dass entweder zu tun. Es scheint, dass Sie eine Art von Kind Klasse verwenden müssen, wie die anderen Poster vorgeschlagen haben. Wenn Sie eine Methode finden, die funktioniert, werden die Entwickler sie wahrscheinlich als einen Fehler in der Zukunft klassifizieren und Ihren Code bei der Aktualisierung auf die nächste Version unterbrechen.

Ich empfehle, die Klasse zu erweitern.

+0

Nono, es ist ein guter Schuss. Ich werde es wahrscheinlich versuchen. Wenn es funktioniert, lasse ich es Sie wissen. –

+0

Ich denke, das wird nur eine Zeichenfolge erstellen $ obj-> publicFunc, was der Name der neuen Funktion ist. Wenn Sie versuchen, es aufzurufen, ist der Bereich wie für eine normale Funktion. –

+1

Ich bekomme das nicht funktioniert: http://chadjohnson.ath.cx:8080/static/anonymous_function.phps. Der Fehler, den ich bekomme, ist "Aufruf zu undefinierter Methode Chad :: publicFunction()". Was könnte ich falsch machen? –

1

Dies ist ein wenig kludgy, aber könnte eine Option sein.

ein Kind Klasse im Interesse

Ihre geschützten Funktion für den Zugriff auf
public class Child extends Parent { 
    public function protectedFunc() { 
     return parent::protectedFunc(); 
    } 
} 

Dann instanziiert eine Instanz von Child statt Parent hinzufügen, wo Sie diese Funktion aufrufen müssen.

+0

Hmm, ja, das sieht nach meiner einzigen Option aus. Vielleicht sollte ich diese Klasse Spy o_O nennen. –

3

Ich würde denken, dass in diesem Fall Refactoring, so dass Sie solche Dinge nicht benötigen, wahrscheinlich der eleganteste Weg zu gehen ist. Wenn man sagt, dass eine Option darin besteht, __call zu verwenden und innerhalb dieses Parsers debug_backtrace zu sehen, welche Klasse die Methode genannt wird. Dann überprüfen Sie einen Freund whitelst

class ProtectedClass { 

    // Friend list 
    private $friends = array('secret' => array('FriendClass')); 

    protected function secret($arg1, $arg2) { 
     // ... 
    } 

    public function __call($method, $args) { 

     $trace = debug_backtrace(); 
     $class = $trace[1]['class']; 
     if(in_array($class, $this->friends[$method])) 
      return $this->$method($args[0], $args[1]); 

     throw new Exception(); 
    } 
} 

Ich denke, ich brauche eine Dusche.

+0

Warum nicht einfach Reflexionen verwenden? – Smar

0

Ich würde darüber nachdenken, was ist mit dem Programmdesign los, wenn ich eine private Funktion aufrufen muss?

Früher war es der Fall sein, wenn

  • Ihre Klasse für mehrere Dinge verantwortlich ist (es ist wirklich zwei oder dre calsses gewickelt zusammen) oder
  • die Regeln der Verkapselung aufgebrochen werden (Utility-Funktionen, für Beispiel)

von jeden Weg, um diese Fragen zu Fuß zu finden, werden Sie nirgends näher an die realen Lösung sein.

+1

Im Allgemeinen ist dies ein guter Rat. Aber manchmal gibt es gute Gründe, Methoden außerhalb ihres definierten Bereichs aufzurufen. Zum Beispiel, wenn Sie eine Methode nicht zu einem Teil Ihrer API machen möchten, sie aber in Ihren Tests aufrufen möchten. Oder in CodeIgniter-Ansichten möchten Sie möglicherweise möchten, dass Ihre Kennwort-Hash-Funktion nicht aus dem Internet aufrufbar ist, Sie sie jedoch in Ihren Tests aufrufen möchten. Im Gegensatz zu C++ hat PHP keine "Freund" -Klassen, die privilegierten Zugriff auf Klasseninterna haben. – qris

+1

Auch wenn Sie eine Drittanbieter-API verwenden, die die Methode nicht verfügbar macht, aber Sie müssen auf diese Methode zugreifen. Definitiv ein gültiger Punkt von Csaba, aber in sehr seltenen Fällen müssen Sie möglicherweise die Regeln brechen. –

-3

Ihre Methode Erklärung geht wie so Angenommen:

protected function getTheFoo() { 
    ... 
} 

protected function setTheFoo($val) { 
    ... 
} 

Verbrauch:

$obj->__get('the_foo'); 
$obj->__set('the_foo', 'myBar'); 

Dies umgeht die geschützten Methoden und geht direkt geradeaus auf die Instanzvariablen.

+0

Ich bekomme das nicht. – Mateng

4

In PHP können Sie dies mit Reflections tun. Um geschützte oder private Methoden aufzurufen, verwenden Sie die Methode setAccessible() http://php.net/reflectionmethod.setaccessible (setzen Sie sie einfach auf TRUE)

+0

Sie sollten sagen, wie Sie die Sache als Antwort tun, nicht um eine andere Antwort zu verknüpfen (in diesem Fall Dokumentation). Sie werden jedoch ermutigt, sich mit Ihrer Quelle und anderen wichtigen Teilen der Dokumentation zu verbinden. – Smar