2012-10-13 16 views
5

Jestem bardzo początkującym w OOP i teraz próbuję napisać jakąś klasę PHP, aby połączyć się z serwerem FTP.PHP-OOP rozszerzające dwie klasy?

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

Uważam, że ciało klasy jest w tej chwili nieistotne.

Głównym problemem jest to, że mam pewne problemy ze zrozumieniem idei OOP.

Chciałem dodać e-maile wysyłane za każdym razem, gdy kod jest uruchamiany. Pobrałem PHPMailer Class i rozszerzony moją klasę z nim:

class ftpConnect extends PHPMailer {...} 

Dodałem kilka zmiennych i metod i wszystko działa jak należy do tego punktu.

Pomyślałem: dlaczego nie dodać wszystkiego do bazy danych. Za każdym razem, gdy użytkownik uruchamia powyższy kod, właściwe informacje powinny być przechowywane w bazie danych.

Mogę edytować mój ftpConnect class i dodać bazę danych łączącą się z konstruktorem, a także kilka innych metod aktualizowania tabel. Ale połączenie z bazą danych i wszystkie te rzeczy mogą być używane przez inne klasy w przyszłości, więc zdecydowanie powinno być realizowane w oddzielnej klasie. Ale mój "główny" ftpConnect class rozszerzył już jedną klasę i nie mógł przedłużyć ani jednej.

Nie mam pojęcia, jak rozwiązać ten problem. Może mój ftpConnect class jest skomplikowany i powinienem go jakoś podzielić na kilka mniejszych klas? Każda pomoc jest doceniana.

+6

podczas tworzenia czegoś, co nazywa się Bogiem Object ** **, który jest pojedynczy obiekt, który odpowiedzialny jest za duży fragment (lub całego) aplikacji. To nie jest dobrze. * Każdy obiekt powinien mieć jedną odpowiedzialność i to wszystko *. Chcesz wysłać pocztę? Mają inny przedmiot do tego. Chcesz zapisać do bazy danych? Mają inny przedmiot do tego. Można je połączyć, przekazując odniesienia do siebie za pośrednictwem konstruktorów lub metod. To się nazywa ** Dependency Injection **. Sprawdź to. –

+0

Niezależne obiekty specjalistyczne są w porządku, tak jak nie oczekujemy od profesora college'u nauczania * wszystkich * przedmiotów z college'u. – wallyk

Odpowiedz

7

Na początek Myślę, że masz wadę w swojej klasie. Twój konstruktor wykonuje pracę. To nie jest to, co konstruktor powinien zrobić we właściwym OOP. Twój konstruktor powinien po prostu ustawić właściwości i powinieneś mieć osobną metodę connect().

Po drugie ftpConnect nigdy nie powinno się przedłużać PHPMailer. Są to dwie zupełnie różne rzeczy. Przeczytaj o Liskov substitution principle jest częścią SOLID principles.

Jeśli twoja klasa musi coś zrobić z bazą danych lub musi wysyłać wiadomości e-mail, musisz wprowadzić te instancje do swojej klasy zamiast ich rozszerzać. Nazywa się to dependency injection, a to ułatwi wykonywanie testów jednostkowych później, ponieważ można z łatwością korzystać z pozornej klasy mailera lub fałszywej klasy bazy danych.

Jeśli chcesz wysyłać wiadomości e-mail, mieć dostęp do bazy danych i używać FTP, potrzebujesz co najmniej 3 różnych (oddzielnych) klas (prawdopodobnie jeszcze więcej, aby zrobić mapowanie dla bazy danych itp.). Zasadniczo każda klasa powinna mieć jedną odpowiedzialność i tylko jedną. Nazywa się to single responsibility principle.

Dla niektórych ogólnych odniesień patrz:

0

To chyba kwestia składu nad dziedziczenia Zobacz ten Prefer composition over inheritance? Wystarczy użyć obiektu mailera wewnątrz swojej klasie i to samo dotyczy DB zamiast swojej klasie powiększenia każdego z nich.

class my_class 
{ 
    private $mailer; 

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

To dobry początek, ale użycie zastrzyku zależności sugerowanego przez @PeeHaa jest prawdopodobnie lepszym pomysłem. – igorw

0

Dla części bazy danych, przechowywania, można utworzyć klasę oddzielna, która ma połączenie z bazą danych. Możesz przekazać instancję tej klasy do klasy ftpConnect poprzez jej konstruktor. Podaj swojej klasie fptConnect właściwość, w której możesz przechowywać ten nowy obiekt bazy danych, dzięki czemu możesz uzyskać dostęp do tego obiektu w całej klasie ftpConnect.

Twoja klasa ftpConnect obecnie ma konstruktora, który będzie albo powrotu true lub false, nie pozwól konstruktor zwraca żadnej wartości, ponieważ wil trzeba zwracać instancję klasy ftpConnect które trzeba będzie przechowywać wewnątrz zmiennej . Można zatem dokonać rzeczywistego połączenia w oddzielnej metodzie. Twoja klasa może wyglądać mniej więcej tak.

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

Oczywiście jest to możliwe, prawdopodobnie będzie dużo bardziej eleganckie rozwiązania. Sposób wysyłania wiadomości e-mail można zrealizować, korzystając z tej samej koncepcji.

Z zewnątrz będzie wyglądać następująco

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

$ftp->connect(); 
Powiązane problemy