我决定编写一个特征,该特征将使用内置函数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);
}
}
?>
答案 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);
}
}
然后,将包装器注入需要使用它的任何类中。