Я очень новичок в ООП, и теперь я пытаюсь написать некоторый PHP-класс для подключения к FTP-серверу.
class ftpConnect { private $server; private $user; private $password; private $connection_id; private $connection_correct = false; public function __construct($server, $user = "anonymous", $password = "anonymous@mail.com") { $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; } } }
Я считаю, что этот класс класса на данный момент незначителен.
Основная проблема заключается в том, что у меня есть некоторые проблемы с пониманием идеи ООП.
Я хотел бы добавлять отправку писем каждый раз, когда код запускается. Я загрузил PHPMailer Class и расширил свой класс:
class ftpConnect extends PHPMailer {...}
Я добавил некоторые переменные и методы, и все работает так, как ожидалось.
Я подумал: почему бы не добавить все в базу данных. Каждый раз, когда пользователь работает над кодом, надлежащая информация должна храниться в базе данных.
Я мог бы отредактировать свой ftpConnect class
и добавить базу данных, подключающуюся к конструктору, и некоторые другие методы для обновления таблиц. Но соединение с базой данных и все эти вещи могут использоваться другими классами в будущем, поэтому это определенно должно быть реализовано в отдельном классе. Но мой «основной» ftpConnect class
уже расширяет один класс и не может распространять ни одного другого.
Я не знаю, как решить эту проблему. Может быть, мой ftpConnect class
сложный, и я должен как-то разделить его на несколько меньших классов? Буду признателен за любую оказанную помощь.
Для начала я думаю, что у вас есть недостаток дизайна в вашем классе. Ваш конструктор выполняет работу. Это не то, что должен сделать конструктор в надлежащем ООП. Ваш конструктор должен просто установить свойства, и у вас должен быть отдельный метод connect()
.
Второй ftpConnect
никогда не должен расширять PHPMailer
. Это две совершенно разные вещи. Читайте о принципе замещения Лискова, он является частью принципов SOLID .
Если вашему классу нужно что-то делать с базой данных или нужно отправлять письма, вам нужно вставлять эти экземпляры в свой класс, а не расширять их. Это называется инъекцией зависимостей, и это упростит последующие модульные тесты, поскольку вы можете легко использовать класс moker mailer или класс макетной базы данных.
Если вы хотите отправлять письма, иметь доступ к базе данных и использовать FTP, вам понадобится как минимум 3 разных (разделенных) класса (возможно, даже больше, чтобы сделать некоторое сопоставление для db и т. Д.). В принципе каждый класс должен иметь одну ответственность и только одну. Это называется принципом единой ответственности .
Для некоторых общих ссылок см.
Вероятно, это вопрос композиции над наследованием. Посмотрите эту предпочтительную композицию над наследованием? Просто используйте почтовый объект внутри вашего класса, а то же, что и для БД, а не для вашего класса, распространяющего любой из них.
class my_class { private $mailer; public function __constructor() { $this->mailer = new Mailer(); } }
Для части сохранения базы данных вы можете создать отдельный класс, который имеет соединение с вашей базой данных. Вы можете передать экземпляр этого класса в свой класс ftpConnect
через его конструктор. Дайте вашему классу fptConnect
свойство, в котором вы можете сохранить этот новый объект базы данных, таким образом вы можете получить доступ к этому объекту во всем классе ftpConnect
.
В вашем классе ftpConnect
настоящее время есть конструктор, который либо вернет true
либо false
, не позволяйте конструктору возвращать какое-либо значение, потому что ему нужно вернуть экземпляр класса ftpConnect, который вам нужно сохранить внутри переменной. Таким образом, вы можете установить фактическое соединение в отдельном методе. Таким образом, ваш класс может выглядеть примерно так.
class FtpConnect { private $server; private $user = "anonymous"; private $password = "anonymous@mail.com"; 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; } } }
Конечно, это возможный способ сделать это, вероятно, будут гораздо более элегантные решения. Способ доставки почты может быть реализован с использованием той же концепции.
Со стороны это будет выглядеть примерно так
$ftp = new FptConnect('server', 'user', 'password', new DbHandler('server', 'user', 'password', 'host')); $ftp->connect();