Есть код для работы сервера на сокетах: Код (Text): <?php require_once __DIR__ . '../../vendor/autoload.php'; use Workerman\Worker; use Server\Mysql; use Server\Logger; use Server\DataInterface; use Server\LoggerInterface; use Workerman\Lib\Timer; class Server { private $users; private $db; private $mysql; public function __construct(DataInterface $mysql, LoggerInterface $logger) { $this->ws_worker = new Worker("websocket://127.0.0.1:8000"); $this->mysql = $mysql; $this->logger = $logger; } public function serverStart() { $this->users = []; $this->ws_worker->count = 4; /* * Стартуем сервер и пингуем БД каждую минуту, что бы сохранить подключение * */ $this->ws_worker->onWorkerStart = function() { $this->logger->save(date("H:m:s"),'Service', 'Сервер запущен'); $time_interval = 60; $timer_id = Timer::add($time_interval, function() { $result = $this->mysql->ping(); }); }; /* * При получении сообщения записываем его в БД и рассылаем пользователям * */ $this->ws_worker->onMessage = function($connection, $data) use (&$users) { $data = json_decode($data); $this->mysql->save('chat',array('time','name','text'),array($data->time,$data->name,$data->message)); $data = json_encode($data); foreach ($this->users as $value) { $value->send($data); } }; /* * При новом подключении уведомляем пользователей, достаем старые сообщения, пишем в лог * */ $this->ws_worker->onConnect = function ($connection) use (&$users) { $connection->onWebSocketConnect = function ($connection) use (&$users) { $this->logger->save(date("H:m:s"),'Service', 'Пользователь присоединился'); $result = $this->mysql->select('chat','time,name,text'); $result = json_encode(['dialog' => $result]); $this->users[$connection->id] = $connection; $this->users[$connection->id]->send($result); foreach ($this->users as $value) { $service = json_encode(['service' => 'Пользователь присоединился.']); $value->send($service); } }; }; /* * При отключении уведомляем пользователей и пишем в лог * */ $this->ws_worker->onClose = function($connection) use (&$users) { $this->logger->save(date("H:m:s"),'Service', 'Пользователь отключился'); foreach ($this->users as $value) { $service = json_encode(['service' => 'Пользователь отключился.']); $value->send($service); } }; Worker::runAll(); } } $server = new Server(new MySql(new Logger(),'localhost','chat','root',''), new Logger()); $server->serverStart(); Вопрос следующий: Этот класс (Server) зависит от класса для работы с БД (Mysql), но класс Server может работать самостоятельно (без класса Mysql). Как ослабить эту зависимость?
Это сервер на сокетах. Если оттуда убрать работу с бд - ничего не изменится. Может мы не понимаем друг друга?
у тебя скрипт работает с БД - все ВЗАИМОСВЯЗАННО --- Добавлено --- СМОТРИ КОД СВОЙ --- Добавлено --- MYSQL --- Добавлено --- ->mysql-> --- Добавлено --- PHP: new MySql(new Logger(),'localhost','chat','root','') это не знает никто, кроме тебя - что там внутри
Ну, например, пропало у нас подключение к базе, чат будет работать. Разве правильно, что класс сервер напрямую взаимодействует с Mysql и логгером ? Не нужна ли там прослойка в виде еще одного класса в который все будет аккумулироваться из класса server и в котором будет работа с бд и логгером ? --- Добавлено --- Код (Text): <?php declare(strict_types = 1); namespace Server; use Server\DataInterface; use Server\Logger; use Server\LoggerInterface; /* * Сделал небольшую обертку для запросов. * Здесь так же пишутся в лог события. Обертку можно еще сильно доработать :) */ class MySql implements DataInterface { private $db; public function __construct(LoggerInterface $logger, $host,string $dbname, string $user, string $password) { $this->logger = $logger; try { $this->db = new \PDO("mysql:host=$host;dbname=$dbname", $user, $password); $this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $this->db->exec("set names utf8"); $this->logger->save(date("H:m:s"),'Service', 'Подключились к Mysql.'); return '</br>Подключились к Mysql.</br>'; } catch(PDOException $e) { $this->logger->save(date("H:m:s"),'Service', 'При подключении к Mysql возникла ошибка.'); return '</br>При подключении к Mysql возникла ошибка: '. $e->getMessage().'</br>'; } } /* * Запрос для пинга в базу * */ public function ping() : string { try { $ping = $this->db->query('SELECT 1'); $ping->setFetchMode(\PDO::FETCH_ASSOC); if ($ping->fetch()) { $this->logger->save(date("H:m:s"),'Service', 'Запрос к Mysql был отправлен (ПИНГ)'); return '</br>Запрос к Mysql был отправлен (ПИНГ).</br>'; } } catch(PDOException $e) { $this->logger->save(date("H:m:s"),'Service', 'Во время пинга Mysql возникла ошибка'); return '</br>Во время пинга Mysql возникла ошибка: '. $e->getMessage().'</br>'; } } /* * Сохранения данных. * 1 параметр - таблица, остальные 2 массива - поля и их значения */ public function save(string $table,array $field, array $value) { $fieldString = implode(',', $field); // превращаем массив в строку array_walk($field, function (&$arr) { $arr = ':'.$arr; }); $valueString = implode(',', $field); try { $stmt = $this->db->prepare("INSERT INTO $table ($fieldString) VALUES ($valueString)"); foreach ($field as $key => $value1) { $stmt->bindParam($field[$key], $value[$key]); } $stmt->execute(); $this->logger->save(date("H:m:s"),'Service', 'Сообщение сохранено в Mysql.'); return '</br>Сообщение сохранено в Mysql.</br>'; } catch(PDOException $e) { $this->logger->save(date("H:m:s"),'Service', 'Во время записи в Mysql произошла ошибка.'); return '</br>Во время записи в Mysql произошла ошибка.</br>'; } } /* * Выборка из БД * 1 параметр - таблица, затем список полей, условие выборки, значения выборки * Последний параметр можно использовать для написания собственного запроса */ public function select(string $table, $field, string $where = NULL, string $value = NULL, string $query = NULL) { try { if ($query == NULL) { if (is_array($field)) { $field = implode(',', $field); // превращаем массив в строку } $stmt = "SELECT $field FROM $table "; if ($where != NULL and $value != NULL) { $stmt.= "WHERE $where = ?"; } $stmt = $this->db->prepare($stmt); $stmt->bindValue(1, $value); $stmt->execute(); $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC); return $rows; } else { $stmt = $this->db->query($query); $rows = $stmt->fetchAll(); return $rows; } } catch(PDOException $e) { $this->logger->save(date("H:m:s"),'Service', 'Во время запроса в Mysql произошла ошибка.'); return '</br>Во время запроса в Mysql произошла ошибка.</br>'; } } Вот, надо только работу с логгером отсюда убрать
а какой еще способ есть ? почему этот метод не айс ? ведь он вообще никак не нагружает сервак конечно, можно время и побольше поставить. например, 2 минуты