从 trait 方法将资源分配给 class 属性

Assign resource to a class property from trait method

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

我需要从 class 的实例内部使用 $this->conn 来使用 ftp 函数。该变量将保持 ftp 连接。我想将连接特征方法返回的值分配给 $this->conn。我想知道是否有办法在 class.

中调用它

我无法在 class 中获取将使用该特征的 $this 变量。如何在 class?

中访问它
<?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!';
        }
    }
}
?>

注意:在 class 构造函数中调用 trait 的 connect 方法是一个很好的解决方案吗?

<?php
class myclass{

use mytrait;

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

}
?>

Traits 可以用来做你想做的事,但最好实际使用 traits 来做它们可以做的事情:分配和读取 class 属性。

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

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

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

所以在构造函数中,只需调用连接方法:

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

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

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

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

考虑一下,这些 class 实例不依赖于 ftp 凭据,它们依赖于 活动的 ftp 连接 。因此,在 class 的构造函数中实际请求 ftp 连接更清晰,而不用在每个 class 中调用 connect()disconnect() ] 实际上需要 ftp 连接。

我们可以想到一个连接包装器 class 来大大简化这里的事情:

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

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