2012-10-13 48 views
5

我是OOP的初学者,现在我正在尝试编写一些PHP类来连接FTP服务器。PHP-OOP扩展两个类?

class ftpConnect { 
    private $server; 
    private $user; 
    private $password; 

    private $connection_id; 
    private $connection_correct = false; 

    public function __construct($server, $user = "anonymous", $password = "[email protected]") { 

    $this->server = $server; 
    $this->user  = $user; 
    $this->password = $password; 

    $this->connection_id  = ftp_connect($this->server); 
    $this->connection_correct = ftp_login($this->connection_id, $this->user, $this->password); 

    if ((!$this->connection_id) || (!$this->connection_correct)){ 
     echo "Error! Couldn't connect to $this->server"; 
     var_dump($this->connection_id); 
     var_dump($this->connection_correct); 
     return false; 
    } else { 
     echo "Successfully connected to $this->server, user: $this->user"; 
     $this->connection_correct = true; 
     return true; 
    } 
    } 
} 

我觉得这个阶级的身体在此刻是微不足道的。

主要问题是我对理解OOP的想法有些问题。

我想在代码运行时每次都添加发送电子邮件。我已经下载PHPMailer Class和扩展我的课吧:

class ftpConnect extends PHPMailer {...} 

我增加了一些变量和方法,一切都会按预期到这一点。

我想:为什么不添加存储在数据库中的一切。每次用户运行代码时,都应该在数据库中存储适当的信息。

我可以编辑我的ftpConnect class并添加连接到构造函数的数据库,以及其他一些更新表的方法。但是数据库连接和所有这些东西将来可能会被其他类使用,所以它绝对应该在单独的类中实现。 但我的“主”ftpConnect class已扩展到一个类,不能再扩展一个。

我不知道如何解决这个问题。也许我的ftpConnect class是复杂的,我应该把它分成几个小班? 任何帮助,非常感谢。

+6

你正在创建什么叫做神** **的对象,这是一个单一的对象,它是负责一大块(或整个)应用程序。这不好。 *每个对象应该有一个单一的责任,就是它*。想要邮寄?有一个不同的对象。想要保存到数据库?有一个不同的对象。您可以通过构造函数或方法将引用传递给对方来连接它们。这就是**依赖注入**。看看它。 –

+0

独立专业对象没问题,就像我们不期望一位大学教授教所有*大学科目一样。 – wallyk

回答

7

对于初学者来说,我认为你的课堂上有一个设计缺陷。你的构造函数正在工作。这不是一个构造函数应该在适当的OOP中做什么。你的构造函数应该设置属性,你应该有一个单独的方法connect()

第二个ftpConnect永远不应该延伸PHPMailer。他们是两个完全不同的东西。阅读关于Liskov substitution principle它是SOLID principles的一部分。

如果你的类需要对数据库做某些事情或者需要发送邮件,你需要将这些实例注入到类中,而不是扩展它们。这称为dependency injection,这将使以后进行单元测试变得很容易,因为您可以轻松使用模拟邮件程序类或模拟数据库类。

如果你想发送邮件,有数据库访问和使用FTP,你至少需要3个不同的(分离的)类(可能更多做一些映射的数据库等)。基本上每个班级都应该有一个责任,只有一个责任。这被称为single responsibility principle

对于一些一般参考文献,参见:

0

这可能组成了继承问题 看到这个 Prefer composition over inheritance? 只需使用你的类里面的邮件对象,这同样适用于数据库,而不是你的类扩展它们。

class my_class 
{ 
    private $mailer; 

    public function __constructor() 
    { 
     $this->mailer = new Mailer(); 
    } 
} 
+0

这是一个好的开始,但使用@PeeHaa建议的依赖注入可能是一个更好的主意。 – igorw

0

对于数据库存储部分,你可以创建一个单独的类,它有与数据库的连接。你可以通过它的构造函数将这个类的一个实例传递给你的ftpConnect类。给你的​​类一个属性,你可以在这里存储这个新的数据库对象,这样你就可以在整个ftpConnect类中访问这个对象。

ftpConnect类目前有一个构造函数,或者返回truefalse,不要让构造函数返回任何值,因为它西港岛线需要返回ftpConnect类的一个实例,您将需要存储在变量中。因此,你可以用一种独立的方法建立实际的连接。所以你的班级可以看起来像这样。

class FtpConnect { 
    private $server; 
    private $user    = "anonymous"; 
    private $password   = "[email protected]"; 
    private $connection_id; 
    private $connection_correct = false; 

    //this will take care of the storage 
    private $database_handler; 

    public function __construct($server, $user, $password, $database_handler) { 
     $this->server = $server; 
     $this->user  = $user; 
     $this->password = $password; 
     $this->database_handler = $database_handler; 

     //store the appropriate data, this will be done everything a new instance is created 
     $this->database_handler->store_data($data_to_store); 
    } 

    public function connect() { 

     //data to store, everytime a connection is made 
     $this->database_handler->store_data($data_to_store); 

     $this->connection_id  = ftp_connect($this->server); 
     $this->connection_correct = ftp_login($this->connection_id, $this->user, $this-  >password); 

     if ((!$this->connection_id) || (!$this->connection_correct)){ 
      echo "Error! Couldn't connect to $this->server"; 
      var_dump($this->connection_id); 
      var_dump($this->connection_correct); 
      return false; 
     } else { 
      echo "Successfully connected to $this->server, user: $this->user"; 
      $this->connection_correct = true; 
      return true; 
     } 
    } 
} 

Ofcourse,这是一个可能的方式做到这一点,有可能西港岛线更加优雅的解决方案。使用相同的概念可以实现邮件完成的方式。

从外面看起来像这样

$ftp = new FptConnect('server', 'user', 'password', new DbHandler('server', 'user', 'password', 'host')); 

$ftp->connect();