我决定编写一个特性,负责使用php内置函数连接和断开与ftp的连接。我想使用特征方法登录,连接和断开与主机的连接。
我需要在类的实例中使用$this->conn
来使用ftp函数。该变量将保持ftp连接。我想为$this->conn
分配connect trait方法返回的值。我想知道是否有办法在课堂内调用它。
我无法在将使用该特征的类中获取$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!';
}
}
}
?>
注意:在类构造函数中调用trait的connect方法可以是一个很好的解决方案吗?
<?php
class myclass{
use mytrait;
public function __construct(){
$this->conn = $this->connect($host, $user, $pass);
}
}
?>
特征可以用来做你想做的事情,但最好实际使用特征来做他们能做的事情:从类属性中分配和读取。
在特征中,当你分配给$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();
}
话虽如此,这是一种相当古怪的管理方式。必须在每个使用该特征的类中手动调用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);
}
}
然后,将该包装器注入需要使用它的任何类。