2012-03-26 3 views
1

Я пишу набор классов, которые обрабатывают простую загрузку файлов с протоколами ftp и ftps (not sftp).Переменные методы в PHP?

Поскольку единственное различие между использованием FTP и FTPS в PHP есть функция подключения, я думал, что я мог бы использовать переменную функцию в виде $connection_function($host);, где $connection_function имеет одно из значений ftp_connect() или ftp_ssl_connect().

Я сделал абстрактный класс, который решает, что использовать. Упрощая для наглядности, я писал:

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"); 
} 

Я получаю ошибку

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

который, очевидно, происходит от загрузки публичной функции ($ хозяина, $ файла, ...) { $ соппы = $ this-> connection_function ($ host); }

Так это происходит со мной, что я написал переменную метод вместо переменной функции, которая, по-видимому, не разрешено (или обработанную, как я ожидал, что будет) в PHP.

Могу ли я делать то, что хочу? Абстрактный класс обрабатывает все функции ftp, и я хотел бы избежать дублирования кода над двумя классами.

Редактировать Теперь, когда я смотрел на нее немного, я вижу, что я могу просто поставить протокольное решение в самом методе Подключение:

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

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

    } 

Но еще мне интересно, есть ли способ делать мои переменные методы? Как бы то ни было, мне по-прежнему приходится дублировать мою обработку ошибок сбрасывания и любой другой код, который я могу разместить внутри этих if-блоков.

ответ

5

Насколько переводчик знает, что вы пытаетесь вызвать эту функцию, а не использовать в качестве переменной:

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

Вместо этого, попробуйте следующее:

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

И как crashspeeder упоминает , вы также можете использовать call_user_func(), вот немного измененная версия его ответа:

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

Для этого конкретного варианта использования это, скорее всего, лучшее решение, так как вы можете легко передать аргументы.

+1

'$ this -> {$ this-> connection_function} ($ host);' другой (в данном случае довольно уродливый) способ сделать то же самое – AD7six

+0

aw ... Я думаю, что фигурные скобки красивы! – user151841

+0

@ AD7six пытался найти способ использования '{}'; однако он вызывает функцию native, а не функцию в классе. –

4

Я бы рекомендовал использовать функцию call_user_func() для вызова функции, которую вы хотите.

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

Вы также можете использовать call_user_func_array(), если вы хотите, чтобы передать массив, содержащий все параметры.

Смежные вопросы