通过特征方法将资源分配给类属性

时间:2019-04-22 12:32:10

标签: php oop traits

我决定编写一个特征,该特征将使用内置函数php与ftp连接和断开连接。我想使用特征方法登录,连接和断开主机连接。

我需要在类的实例内部使用$this->conn来使用ftp函数。该变量将保持ftp连接。我想将connect trait方法返回的值分配给$this->conn。我想知道是否可以在课堂上调用它。

我无法在使用特质的类中获取$this变量。如何在课堂上访问它?

<?php
trait ConnectionHelper
{
    public function connect(string $host, string $user, string $pwd)
    {
        $this->conn = ftp_connect($host);
        if ($this->conn && ftp_login($this->conn, $user, $pwd)) {
            ftp_pasv($this->conn, true);
            echo "Connected to: $host !";
        }
        return $this->conn;
    }
    public function disconnect()
    {
        return ftp_close($this->conn);
    }
}

class FTPManager
{
    use ConnectionHelper;
    private $url;
    private $user;
    private $password;

    /* Upload */
    public function upload(array $inputFile, string $dir = null)
    {
        if (!is_null($dir)) {
            ftp_chdir($this->conn, "/$dir/");
        }
        $upload = ftp_put($this->conn, $inputFile['name'], $inputFile['tmp_name'], FTP_BINARY);
        if ($upload) {
            echo 'File uploaded!';
        }
    }
}
?>

NB:可以是在类构造函数中调用trait的connect方法的好方法吗?

<?php
class myclass{

use mytrait;

public function __construct(){
    $this->conn = $this->connect($host, $user, $pass);
}

}
?>

1 个答案:

答案 0 :(得分:0)

特质可以用来做你想做的事,但是最好使用特质来做它们可以做的事:分配和读取类属性。

在特征中,当您分配给$this->conn时:

$this->conn = ftp_connect($host);

为使用特征的类实例定义了属性。因此,无需使用$this->conn = $this->connect(),因为$this->conn已包含连接资源。

因此在构造函数中,只需调用connect方法:

public function __construct()
{
    $this->connect($host, $user, $pass);
    // $this->conn will now contain the connection made in connect()
}

无需在特征中使用return $this->conn;。为确保您释放资源,请从disconnect()的析构函数中调用FTPManager

public function __destruct()
{
    $this->disconnect();
}

话虽这么说,这是一种相当古怪的管理方式。必须在每个使用trait的类中手动调用connect()容易出错,并且可能导致可维护性问题(这些类中的每个类都需要了解ftp凭据,例如,将它们紧紧地耦合到配置中)。

考虑一下,这些类实例不依赖于ftp凭据,它们依赖于活动的ftp连接。这样,在类的构造函数中实际请求ftp连接,而不必在每个实际需要ftp连接的类中都调用connect()disconnect()会更干净。

我们可以想到一个连接包装类,它将大大简化这里的事情:

class FTPWrapper {
    private $connection;
    public function __construct(string $host, string $user, string $pwd)
    {
        $this->connect($host, $user, $pwd);
    }
    public function __destruct()
    {
        $this->disconnect();
    }
    public function getConnection()
    {
        return $this->connection;
    }
    private function connect(string $host, string $user, string $pwd): void
    {
        $this->connection = ftp_connect($host);
        if ($this->connection && ftp_login($this->connection, $user, $pwd)) {
            ftp_pasv($this->connection, true);
            echo "Connected to: $host !";
        }
    }
    private function disconnect(): void
    {
        ftp_close($this->conn);
    }
}

然后,将包装器注入需要使用它的任何类中。