2012-10-13 46 views
5

Tôi rất mới bắt đầu với OOP và bây giờ tôi đang cố gắng viết một số lớp PHP để kết nối với máy chủ FTP.PHP-OOP mở rộng hai lớp?

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

Tôi cho rằng nội dung của lớp không đáng kể vào lúc này.

Vấn đề chính là tôi gặp một số vấn đề khi hiểu ý tưởng OOP.

Tôi muốn thêm email gửi mỗi lần, khi mã được chạy. Tôi đã tải PHPMailer Class và mở rộng lớp học của tôi với nó:

class ftpConnect extends PHPMailer {...} 

Tôi đã thêm một số biến và các phương pháp và mọi thứ hoạt động như mong đợi đến thời điểm đó.

Tôi nghĩ: tại sao không thêm lưu trữ mọi thứ trong cơ sở dữ liệu. Mỗi người dùng chạy trên mã, thông tin thích hợp nên được lưu trữ trong cơ sở dữ liệu.

Tôi có thể chỉnh sửa ftpConnect class và thêm cơ sở dữ liệu kết nối với hàm tạo và một số phương pháp khác để cập nhật bảng. Nhưng cơ sở dữ liệu kết nối và tất cả những thứ đó có thể được sử dụng bởi các lớp khác trong tương lai, vì vậy nó chắc chắn nên được thực hiện trong lớp riêng biệt. Nhưng "chính" ftpConnect class của tôi đã mở rộng một lớp và không thể mở rộng thêm một lớp nữa.

Tôi không biết làm thế nào tôi có thể giải quyết vấn đề này. Có lẽ tôi ftpConnect class là phức tạp và tôi bằng cách nào đó nên chia nó thành vài lớp nhỏ hơn? Bất kỳ trợ giúp nào được đánh giá cao.

+6

Bạn đang tạo những gì được gọi là Thiên Chúa Object ** **, mà là một đối tượng duy nhất có trách nhiệm cho một phần lớn (hoặc toàn bộ) ứng dụng. Điều đó không tốt. * Mỗi đối tượng nên có một trách nhiệm duy nhất, và đó là nó *. Muốn gửi thư? Có một đối tượng khác cho điều đó. Bạn muốn lưu vào cơ sở dữ liệu? Có một đối tượng khác cho điều đó. Bạn có thể kết nối chúng bằng cách chuyển các tham chiếu đến nhau thông qua các hàm tạo hoặc các phương thức. Đó được gọi là ** Dependency Injection **. Tìm kiếm. –

+0

Các đối tượng chuyên biệt độc lập là tốt, giống như chúng ta không mong đợi một giáo sư đại học dạy * tất cả * môn học đại học. – wallyk

Trả lời

7

Để bắt đầu tôi nghĩ bạn có lỗi thiết kế trong lớp học của bạn. Nhà xây dựng của bạn đang làm việc. Đó không phải là những gì một nhà xây dựng nên làm trong OOP thích hợp. Nhà xây dựng của bạn chỉ nên thiết lập các thuộc tính và bạn nên có một phương thức riêng biệt connect().

Thứ hai ftpConnect không bao giờ được mở rộng PHPMailer. Họ là hai điều hoàn toàn khác nhau. Đọc về số Liskov substitution principle nó là một phần của SOLID principles.

Nếu lớp học của bạn cần làm điều gì đó với cơ sở dữ liệu hoặc cần gửi thư, bạn cần phải tiêm những trường hợp đó vào lớp của bạn thay vì mở rộng chúng. Điều này được gọi là dependency injection và điều này sẽ làm cho nó dễ dàng để làm bài kiểm tra đơn vị sau này, bởi vì bạn có thể dễ dàng sử dụng một lớp người giả thư hoặc một lớp cơ sở dữ liệu giả.

Nếu bạn muốn gửi thư, có quyền truy cập cơ sở dữ liệu và sử dụng FTP, bạn sẽ cần ít nhất 3 lớp khác nhau (có thể là nhiều hơn để thực hiện một số ánh xạ cho db, v.v.). Về cơ bản, mỗi lớp chỉ có một trách nhiệm và một lớp duy nhất. Đây được gọi là single responsibility principle.

Đối với một số tài liệu tham khảo chung xem:

0

Đây có thể là một câu hỏi của thành phần trên thừa kế Xem này Prefer composition over inheritance? Chỉ cần sử dụng các đối tượng bên trong bưu phẩm lớp học của bạn và cùng đi cho DB chứ không phải là lớp học của bạn kéo dài bất kỳ trong số họ.

class my_class 
{ 
    private $mailer; 

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

Đây là một khởi đầu tốt, nhưng sử dụng tiêm phụ thuộc như đề xuất bởi @PeeHaa có lẽ là một ý tưởng tốt hơn. – igorw

0

Đối với phần cơ sở dữ liệu lưu trữ, bạn có thể tạo ra một lớp riêng biệt, trong đó có một kết nối đến cơ sở dữ liệu của bạn. Bạn có thể chuyển một thể hiện của lớp này tới lớp ftpConnect của bạn thông qua hàm tạo của nó. Cung cấp cho lớp fptConnect thuộc tính của bạn nơi bạn có thể lưu trữ đối tượng cơ sở dữ liệu mới này, theo cách này bạn có thể truy cập đối tượng này trong toàn bộ lớp ftpConnect của mình.

lớp ftpConnect của bạn hiện đang có một constructor mà một trong hai sẽ trở lại true hoặc false, đừng để các nhà xây dựng trả lại bất kỳ giá trị, bởi vì nó wil cần phải trả lại một thể hiện của lớp ftpConnect mà bạn sẽ cần phải lưu trữ bên trong một biến . Do đó, bạn có thể thực hiện kết nối thực tế theo một phương pháp riêng biệt. Vì vậy, lớp học của bạn có thể trông giống như thế này.

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

Tất nhiên đây là cách có thể để làm điều đó, có thể là giải pháp thanh lịch hơn. Cách gửi thư được thực hiện có thể được thực hiện bằng cách sử dụng cùng một khái niệm.

Từ bên ngoài, nó sẽ giống như thế này

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

$ftp->connect();