From abfb1bc532b2bad7d84cdd8d023c99e8a966c585 Mon Sep 17 00:00:00 2001 From: User Date: Mon, 29 May 2023 02:45:49 +0300 Subject: [PATCH] Init --- .gitignore | 3 + README.md | 4 + composer.json | 20 ++++ src/Exception/MysqlException.php | 8 ++ src/MysqlStorage.php | 166 +++++++++++++++++++++++++++++++ src/MysqlStorageData.php | 77 ++++++++++++++ src/MysqlStorageInterface.php | 97 ++++++++++++++++++ 7 files changed, 375 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 composer.json create mode 100644 src/Exception/MysqlException.php create mode 100644 src/MysqlStorage.php create mode 100644 src/MysqlStorageData.php create mode 100644 src/MysqlStorageInterface.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..31dc5a1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea/ +/vendor +composer.lock \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..a28cad0 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +### Rmphp/Storage + +DB component for **Rmphp** + diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..e9340c0 --- /dev/null +++ b/composer.json @@ -0,0 +1,20 @@ +{ + "name": "rmphp/storage", + "license": "proprietary", + "authors": [ + { + "name": "Yuri Zuev", + "email": "y_zuev@mail.ru" + } + ], + "require": { + "php": "^8.1", + "ext-mysqli": "*" + }, + "autoload": { + "psr-4": { + "Rmphp\\Storage\\": "src/" + } + } + +} diff --git a/src/Exception/MysqlException.php b/src/Exception/MysqlException.php new file mode 100644 index 0000000..93469d0 --- /dev/null +++ b/src/Exception/MysqlException.php @@ -0,0 +1,8 @@ +mysqli = new mysqli($params['host'], $params['user'], $params['pass'], $params['base']); + // выводим ошибку при неудачном подключении + if ($this->mysqli->connect_errno) { + throw new Exception($this->mysqli->connect_errno); + } + $this->mysqli->set_charset("utf8"); + if(!empty($params['logsEnable'])) $this->logsEnabled = true; + } + + /** @inheritDoc */ + public function mysql() : Mysqli { + return $this->mysqli; + } + + /** @inheritDoc */ + public function query(string $sql) : bool|mysqli_result + { + try{ + $result = $this->mysqli->query($sql); + // запись в log + ($this->mysqli->errno) + ? $this->addLog("Err - SQL: ".$sql." | error: ".$this->mysqli->error) + : $this->addLog("OK - ".$sql); + return $result; + } + /* 8.1.0 Теперь по умолчанию установлено значение MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT и выбрасывается исключение. Ранее оно было MYSQLI_REPORT_OFF. */ + catch (Exception $exception){ + $this->addLog("Err - SQL: ".$sql." | error: ".$this->mysqli->error); + return false; + } + } + + /** @inheritDoc */ + public function add(string $tbl, array $arr, bool $update = false) : bool { + foreach ($arr as $key => $value) { + $col[] = "`$key`"; + $val[] = ($value !== NULL) ? "'$value'" : "NULL"; + $upd[] = ($value !== NULL) ? "`$key`='$value'" : "`$key`=NULL"; + } + // Собираем в строки для использования в запросе + $col = implode(", ", $col); + $val = implode(", ", $val); + + if (!$update) { + $sql = "insert low_priority into ".$this->escapeStr($tbl)." (".$col.") values (" . $val . ")"; + } else{ + $sql = "insert low_priority into ".$this->escapeStr($tbl)." (".$col.") values (".$val.") on duplicate key update ".implode(", ", $upd); + } + return $this->query($sql); + } + + /** @inheritDoc */ + public function edit(string $tbl, array $arr, string $case, bool $ignore=false) : bool { + foreach ($arr as $key => $value) { + $isql[] = ($value !== NULL) ? "`$key`='$value'" : "`$key`=NULL"; + } + $where = (preg_match("'^[0-9]+$'",$case)) ? "id = '".(int) $case."'" : $case; + if(empty($ignore)) { + $sql = "update low_priority " . $this->escapeStr($tbl) . " set " . implode(", ", $isql) . " where " . $where; + } else { + $sql = "update low_priority ignore " . $this->escapeStr($tbl) . " set " . implode(", ", $isql) . " where " . $where; + } + return $this->query($sql); + } + + /** @inheritDoc */ + public function replace(string $tbl, array $arr) : bool { + foreach ($arr as $key => $value) { + $col[] = "`$key`"; + $val[] = ($value !== NULL) ? "'$value'" : "NULL"; + } + // Собираем в строки для использования в запросе + $col = implode(", ", $col); + $val = implode(", ", $val); + + $sql = "replace low_priority into ".$this->escapeStr($tbl)." (".$col.") values (".$val.")"; + return $this->query($sql); + } + + /** @inheritDoc */ + public function del(string $tbl, string $case) : bool { + $where = (preg_match("'^[0-9]+$'",$case)) ? "id = '".(int) $case."'" : $case; + $sql = "delete low_priority from ".$this->escapeStr($tbl)." where ".$where; + // возвращаем число затронутых строк/false + return $this->query($sql); + } + + /** @inheritDoc */ + public function read(string $sql, int $ln = 0, int $numPage = 1) : bool|MysqlStorageData { + if ($ln > 1) { + $cnts = $this->query($sql)->num_rows; + } + // часть строки запроса с лимит + switch (true){ + case ($ln > 1 || $numPage > 1) : $limit = " limit ".(($numPage * $ln) - $ln).", ".$ln; break; + case ($ln == 1): $limit = " limit 0, 1"; break; + default: $limit = ""; + } + + $result = $this->query($sql.$limit); + if (!$result || $result->num_rows == 0) return false; + + $data = new MysqlStorageData($result); + $data->count = $cnts ?? 0; + return $data; + } + + /** @inheritDoc */ + public function chktbl(string $tbl) : bool { + $result = $this->mysqli->query("SHOW TABLES LIKE '".$this->escapeStr($tbl)."'"); + if ($result->num_rows == 0) { + $this->addLog(__METHOD__.":"." Err - Table ".$tbl." doesn't exist"); return false; + } + $this->addLog(__METHOD__.":"." OK - Table ".$tbl." exist"); + return true; + } + + /** @inheritDoc */ + public function escapeReg(string $var) : ?string { + if(!isset($var)) return null; + return trim(addcslashes($this->mysqli->real_escape_string($var), "%_")); + } + + /** @inheritDoc */ + public function escapeStr(?string $var) : ?string { + if(!isset($var)) return null; + return trim($this->mysqli->real_escape_string($var)); + } + + /** @inheritDoc */ + public function addLog(string $log) : void { + if($this->logsEnabled) $this->log[] = $log; + } + + /** @inheritDoc */ + public function getLogs() : array { + return $this->log; + } + + /** @inheritDoc */ + public function getLastLog() : string { + return $this->log[count($this->log)-1]; + } + +} \ No newline at end of file diff --git a/src/MysqlStorageData.php b/src/MysqlStorageData.php new file mode 100644 index 0000000..b16b60a --- /dev/null +++ b/src/MysqlStorageData.php @@ -0,0 +1,77 @@ +result = $result; + } + + /** + * @return bool + */ + public function isResult() : bool { + return isset($this->result); + } + + /** + * @return \mysqli_result|null + */ + public function getMysqlResult() : ?\mysqli_result { + return $this->result; + } + + /** + * @return iterable + */ + public function fatch(): iterable { + if(!empty($this->arrayData)) return $this->arrayData; + if(!$this->result) return []; + return $this->generator(); + } + + + public function fatchOne(int $index = 0) : array { + if(!$this->result) return []; + $this->result->data_seek($index); + return $this->result->fetch_assoc(); + } + + /** + * @return array + */ + public function getData() : array { + if(!empty($this->arrayData)) return $this->arrayData; + if(!$this->result) return []; + $this->result->data_seek(0); + while ($row = $this->result->fetch_assoc()) { + $this->arrayData[] = $row; + } + return $this->arrayData; + } + + /** + * @return iterable + */ + private function generator() : iterable { + $this->result->data_seek(0); + while ($row = $this->result->fetch_assoc()) { + yield $row; + } + } + + public function __destruct() { + if($this->result) $this->result->close(); + } + +} \ No newline at end of file diff --git a/src/MysqlStorageInterface.php b/src/MysqlStorageInterface.php new file mode 100644 index 0000000..d441a7d --- /dev/null +++ b/src/MysqlStorageInterface.php @@ -0,0 +1,97 @@ +