2012-03-26 14 views
1

Ich schreibe eine Reihe von Klassen, die einfache Dateiuploads sowohl mit ftp als auch mit ftps (nicht sftp) verarbeiten.Variable Methoden in PHP?

Da der einzige Unterschied zwischen der Verwendung von FTP und FTPS in PHP ist die Verbindungsfunktion, dachte ich, dass ich eine variable Funktion in Form verwenden könnte $connection_function($host);, wo $connection_function die eine der beiden Werte ftp_connect() oder ftp_ssl_connect() hat.

Ich habe eine abstrakte Klasse, die entscheidet, welche zu verwenden. Vereinfachen für Klarheit, schrieb ich:

abstract class uploader { 

    protected $connection_function; 

    public function __construct($protocol) { 
    if ($protocol == "ftp") { 
     $this->connection_function = "ftp_connect"; 
    } elseif ($protocol == "sftp") { 
     $this->connection_function = "ftp_ssl_connect"; 
    } 
    } 

    public function upload($host, $file, ...) { 
    $conn = $this->connection_function($host); 
    } 
} 

class ftp_uploader extends uploader { 
    parent::__construct("ftp"); 
} 

class ftps_uploader extends uploader { 
    parent::__construct("ftps"); 
} 

Ich erhalte den Fehler

PHP Fatal error: Call to undefined method ftp_uploader::connection_function()

die offensichtlich kommt aus public function upload ($ host, $ file, ...) { $ conn = $ this-> connection_function ($ host); }

So kommt es mir, dass ich eine Variable Methode geschrieben haben, statt einer variablen Funktion, die offenbar nicht erlaubt ist (oder so behandelt, als ich es erwarten) in PHP.

Kann ich tun was ich will? Die abstrakte Klasse behandelt alle ftp-Funktionen, und ich möchte vermeiden, Code über zwei Klassen zu duplizieren.

bearbeiten Nun, da ich es ein bisschen geschaut haben, wie ich sehe, dass ich nur das Protokoll Entscheidung in der conection Methode selbst setzen kann: Ich frage mich

public function upload($host, $file, ...) { 

    if ($protocol == "ftp") { 
     $conn = ftp_connect($host); 
    } elseif ($protocol == "sftp") { 
     $cont = ftp_ssl_connect($host); 
    } 

    } 

Aber noch ist es eine Möglichkeit, um meine variablen Methoden zu machen? So wie es ist, muss ich immer noch meine Fehlerbehandlung bei der Vermeidung von Fehlern und jeden anderen Code, den ich in diese if-Blöcke einfügen möchte, duplizieren.

Antwort

5

Soweit der Interpreter weiß, sind Sie, dass die Funktion aufzurufen versuchen, nicht verwenden als eine Variable ist:

public function upload($host, $file, ...) { 
    $conn = $this->connection_function($host); 
} 

Stattdessen versuchen Sie dies:

public function upload($host, $file, ...) { 
    $func = $this->connection_function; 
    $conn = $func($host); 
} 

Und wie crashspeeder erwähnt Sie können auch call_user_func() verwenden, hier ist eine leicht modifizierte Version seiner Antwort:

Für diesen speziellen Anwendungsfall ist das wahrscheinlich die beste Lösung, da Sie die Argumente einfach weitergeben können.

+1

'$ this -> {$ this-> connection_function} ($ host);' ist eine andere (in diesem Fall ziemlich hässlich) Art und Weise das gleiche zu tun – AD7six

+0

aw ... Ich denke, geschweifte Klammern sind hübsch! – user151841

+0

@ AD7six versuchte einen Weg zu finden, ''} zu verwenden; Allerdings ruft er eine native Funktion auf, keine Funktion in der Klasse. –

4

Ich würde empfehlen, call_user_func() zu verwenden, um die gewünschte Funktion aufzurufen.

public function upload($host, $file, ...) { 
    $conn = call_user_func($this->connection_function,$host, $param2, $param3); 
} 

Sie können auch call_user_func_array() verwenden, wenn Sie alle Ihre Parameter enthält ein Array übergeben werden soll.