diff --git a/help/basic_usage/usage_preparation.md b/help/basic_usage/usage_preparation.md new file mode 100644 index 0000000..5248fec --- /dev/null +++ b/help/basic_usage/usage_preparation.md @@ -0,0 +1,24 @@ +# Подготовка к использованию + +Чтобы начать пользоваться классом, необходимо для начала прописать настройки соединения с базой данных. + +Для этого создадим класс [DBConfig](../class_desc/DBConfig.md) с конфигурацией подключения к базе данных: + +```php +$db_config = new DBConfig( + DBDriver::PostgreSQL, + 'localhost', + 5432, + 'my_database', + 'admin', + 'secret_password', + 'encryption_key' +); +``` + +Первым параметром идёт драйвер СУБД, представленный перечислением [DBDriver](../class_desc/DBDriver.md), затем сервер БД, порт, её имя, пользователь, пароль и ключ для шифрования (_если используете действия интерфейса ISerializable_). + +Итак, настройки созданы, время создать сам класс [Database](../class_desc/Database.md) + + +[На главную](../index.md) | [Следующий пункт](../index.md) \ No newline at end of file diff --git a/help/class_desc/DBConfig.md b/help/class_desc/DBConfig.md new file mode 100644 index 0000000..64a665a --- /dev/null +++ b/help/class_desc/DBConfig.md @@ -0,0 +1,108 @@ +# Класс `DBConfig` + +## Описание + +Класс предназначен для хранения конфигурации подключения к базе данных. Реализует интерфейс `ISerializable`, позволяющий +сериализировать и десериализировать объект класса в строку формата JSON. + +## Пространство имен и зависимости + +```php +namespace goodboyalex\php_db_components_pack\models; + +use goodboyalex\php_components_pack\classes\Encryptor; +use goodboyalex\php_components_pack\interfaces\ISerializable; +use goodboyalex\php_db_components_pack\enums\DBDriver; +``` + +## Поля + +| Поле | Тип | Описание | +|:-----------:|:----------:|---------------------------------| +| `$Host` | `string` | Хост базы данных | +| `$Port` | `int` | Порт базы данных | +| `$Name` | `string` | Имя базы данных | +| `$UserName` | `string` | Имя пользователя базы данных | +| `$Password` | `string` | Пароль пользователя базы данных | +| `$Driver` | `DBDriver` | Тип драйвера базы данных | +| `$Chipper` | `string` | Пароль шифрования | + +## Методы + +### Конструктор (`__construct`) + +Создает экземпляр класса с заданными параметрами подключения к базе данных. + +**Параметры** + +- `$driver`: тип драйвера базы данных (`DBDriver`) +- `$host`: хост базы данных (`string`) +- `$port`: порт базы данных (`int`) +- `$name`: имя базы данных (`string`) +- `$userName`: имя пользователя базы данных (`string`) +- `$password`: пароль пользователя базы данных (`string`) +- `$chipper`: пароль шифрования (`string`) + +**Возвращаемое значение**: None + +--- + +### Метод `UnSerialize(string $serialized)` + +Десериализирует переданный JSON-строку и восстанавливает состояние объекта. + +**Параметры** + +- `$serialized`: строка, содержащая сериализированные данные (`string`) + +**Возвращаемое значение**: None + +--- + +### Метод `Serialize()` + +Сериализирует состояние объекта в JSON-строку. + +**Возвращаемое значение** + +- `string`: сериализированная строка + +--- + +## Примеры использования + +Пример создания экземпляра класса и его сериализации: + +```php +$config = new DBConfig( + DBDriver::PostgreSQL, + 'localhost', + 5432, + 'my_database', + 'admin', + 'secret_password', + 'encryption_key' +); + +$serializedData = $config->Serialize(); +echo $serializedData; +``` + +Пример восстановления состояния объекта из сериализированной строки: + +```php +// Предположим, мы получили сериализированные данные ранее +$serializedData = '{"host":"localhost","port":5432,"name":"my_database","user":"admin","password":"encrypted_password","driver":1}'; + +$config = new DBConfig(); +$config->UnSerialize($serializedData); + +echo $config->Host; // Выведет: localhost +``` + +## Дополнительная информация + +Данный класс является частью пакета `goodboyalex/php_db_components_pack`. Для полноценной работы рекомендуется +ознакомиться с документацией по пакету и зависимым компонентам. + +[На главную](../index.md) \ No newline at end of file diff --git a/help/class_desc/DBDriver.md b/help/class_desc/DBDriver.md new file mode 100644 index 0000000..1dbb294 --- /dev/null +++ b/help/class_desc/DBDriver.md @@ -0,0 +1,55 @@ +# Перечисление `DBDriver` + +## Описание + +Перечисление представляет собой набор констант, определяющих типы драйверов баз данных, поддерживаемых системой. +Используется совместно с библиотекой PHP PDO для идентификации различных типов СУБД. + +## Пространство имен и зависимости + +```php +namespace goodboyalex\php_db_components_pack\enums; + +use goodboyalex\php_components_pack\traits\EnumExtensionsTrait; +``` + +## Константы + +| Константа | Значение | Описание | +|:------------:|:--------:|-----------------------| +| `MySQL` | `0` | Драйвер MySQL | +| `MSSQL` | `1` | Драйвер MS SQL Server | +| `PostgreSQL` | `2` | Драйвер PostgreSQL | +| `OracleDB` | `3` | Драйвер Oracle | +| `SQLite` | `4` | Драйвер SQLite | + +## Особенности реализации + +Используется trait `EnumExtensionsTrait`, предоставляющий дополнительные методы для работы с перечислениями, такие как +преобразование значений в целые числа и обратно. + +## Использование + +Примеры использования перечисления: + +```php +use goodboyalex\php_db_components_pack\enums\DBDriver; + +// Получение значения по имени +$dbType = DBDriver::MySQL; + +// Проверка типа драйвера +if ($dbType === DBDriver::MySQL) + echo "Это MySQL"; +``` + +## Совместимость + +Перечисление совместимо с современными версиями PHP, начиная с версии 8.1, поддерживающей нативные перечисления ( +`enum`). Если используется более ранняя версия PHP, возможно потребуется альтернативная реализация на основе классов или +сторонних пакетов. + +--- + +Этот класс является частью библиотеки `goodboyalex/php_db_components_pack` и предназначен для унификации работы с +различными системами управления базами данных посредством стандартного интерфейса PDO. \ No newline at end of file diff --git a/help/class_desc/Database.md b/help/class_desc/Database.md new file mode 100644 index 0000000..d6dccb6 --- /dev/null +++ b/help/class_desc/Database.md @@ -0,0 +1,492 @@ +# Класс `Database` + +## Описание + +Класс предназначен для взаимодействия с базами данных посредством библиотеки **PDO**. Данный класс предоставляет методы +для различных операций с базой данных, включая выполнение запросов, управление транзакциями, получение данных и +модификацию таблиц. + +## Пространство имен + +```php +namespace goodboyalex\php_db_components_pack\classes; +``` + +## Автор и версия + +**Автор:** Александр Бабаев +**Версия:** 1.0 +**Последнее обновление:** 1.0 + +## Основные возможности + +### Создание и удаление класса + +* **Конструктор (`__construct`)**: Устанавливает подключение к базе данных и принимает анонимную функцию обработки + исключений. +* **Деструктор (`__destruct`)**: Завершает работу соединения с базой данных. + +### Управление транзакциями + +* `InitTransaction()`: Начало новой транзакции. +* `InTransaction()`: Проверка статуса активной транзакции. +* `Commit()`: Фиксация изменений в базе данных. +* `RollBack()`: Отмена изменений в рамках текущей транзакции. + +### Выполнение запросов + +* `Query($query, $params)`: Выполняет произвольный SQL-запрос и возвращает ассоциативный массив результатов. +* `QueryFirst($query, $params)`: Возвращает первую строку результата запроса. +* `QueryLast($query, $params)`: Возвращает последнюю строку результата запроса. +* `Execute($query, $params)`: Выполняет запрос изменения данных (например, INSERT/UPDATE/DELETE). + +### Вставка + +* `Insert($table, $row)`: Добавление одной записи в указанную таблицу. +* `InsertMany($table, ...$sources)`: Массовая вставка нескольких записей одновременно. + +### Получение + +* `GetRow($table, $where, $columns, $className)`: Выборка одной записи и создание соответствующего объекта модели. +* `GetRows($table, $where, $columns, $className)`: Выборка множества записей и преобразование их в объекты модели. +* `GetCol ($table, $column, $where)`: Выборка столбца. +* `GetValue ($table, $column, $where)`: Выборка конкретной ячейки таблицы. + +### Обновление + +* `Update($table, $item)`: Обновление одной записи в указанной таблице. +* `UpdateMany($table, ...$items)`: Обновление сразу нескольких записей. + +### Удаление + +* `Delete($table, $where)`: Удаление записей по заданному условию. + +### Подсчёт количества / существование записи + +* **`Count($table, $where)`**: Подсчет количества записей, соответствующих условиям. +* **`IsExist($table, $where)`**: Проверка существования хотя бы одной записи по указанному условию. + +### Управление таблицами + +* **`CreateTable($tableName, $dbItemClass)`**: Создание новой таблицы на основе описания класса модели. +* **`DropTable($tableName)`**: Удаление существующей таблицы. +* **`IsTableExist($tableName)`**: Проверка наличия таблицы в базе данных. + +--- + +## Методы подробно + +### 1. Конструктор (`__construct`) + +Создает новое подключение к базе данных и устанавливает обработчик исключений. + +**Параметры** + +- `$config`: Объект конфигурации подключения типа `DBConfig`. +- `$onException`: Функция обратного вызова для обработки исключений. Принимается анонимная функция формата: + `function (Exception $e, bool $isTerminate): void`, где `$e` - исключение, `$isTerminate` - требуется ли прерывание + выполнения или это исключение нужно просто показать (или занести в журнал). + +**Пример использования** + +```php +$config = new DBConfig('mysql', 'localhost', 'database_name', 'username', 'password'); +$db = new Database($config, function(Exception $e, bool $terminate) { + // Создаём текст ошибки + $message = "Ошибка: {$e->getMessage()}"; + // Если смертельная + if ($terminate) + // - то убиваю скрипт + die($message); + else + // - нет? Просто выведу сообщение + echo $message; +}); +``` + +### 2. Деструктор (`__destruct`) + +Закрывает активное соединение с базой данных. + +**Возвращаемое значение:** Нет возвращаемого значения. + +### 3. Транзакции + +#### Создание транзакции (`InitTransaction()`) + +Начинает новую транзакцию в базе данных. + +**Возвращаемое значение:** void. + +#### Проверка существования транзакции (`InTransaction()`) + +Проверяет, активна ли транзакция. + +**Возвращаемое значение:** true — транзакция активна, false — неактивна. + +#### Фиксация транзакций (`Commit()`) + +Фиксирует выполненную транзакцию. + +**Возвращаемое значение:** void. + +#### Откат транзакций (`RollBack()`) + +Отменяет активные изменения транзакции. + +**Возвращаемое значение:** void. + +### 4. Выполнение запросов + +#### Произвольный запрос (`Query()`) + +Выполняет произвольный SQL-запрос и возвращает результат в виде массива. + +**Параметры** + +- `$query`: Строка с SQL-запросом. +- `$params`: Массив параметров для подготовки запроса. + +**Возвращаемое значение:** Ассоциативный массив или false в случае ошибки. + +#### Первая строка запроса (`QueryFirst()`) + +Получает первую строку результата запроса. + +**Возвращаемое значение:** Ассоциативный массив первой строки или false. + +#### Последняя строка запроса (`QueryLast()`) + +Получает последнюю строку результата запроса. + +**Возвращаемое значение:** Ассоциативный массив последней строки или false. + +#### Изменяющие запросы (`Execute()`) + +Выполняет запросы модификации данных (INSERT, UPDATE, DELETE). + +**Возвращаемое значение:** Число затронутых строк или false. + +### 5. Вставка данных + +#### Одинарная вставка (`Insert()`) + +Вставляет один объект в базу данных. + +**Параметры** + +- `$table`: Имя целевой таблицы. +- `$row`: Объект, реализующий интерфейс `IDBItem`. + +**Возвращаемое значение:** Идентификатор созданной записи, -1 или false в случае ошибки. + +#### Массовая вставка (`InsertMany()`) + +Вставляет несколько объектов одновременно. + +**Параметры** + +- `$table`: Имя целевой таблицы. +- `...$sources`: Список объектов, реализующих интерфейс `IDBItem`. + +**Возвращаемое значение:** Массив идентификаторов новых записей или false. + +### 6. Получение данных + +#### Получение одного объекта (`GetRow()`) + +Получает одну запись из базы данных и создаёт экземпляр указанного класса. + +**Параметры** + +- `$table`: Имя таблицы. +- `$where`: Условие выбора (объект `ConditionBuilder`). +- `$columns`: Необходимые колонки (массив). +- `$className`: Полное имя класса, реализующего интерфейс `IDBItem`. + +**Возвращаемое значение:** Экземпляр указанного класса или false. + +#### Получение набора объектов (`GetRows()`) + +Получает список объектов из базы данных. + +**Параметры** + +- `$table`: Имя таблицы. +- `$where`: Условие выбора (объект `ConditionBuilder`). +- `$columns`: Нужные столбцы (массив). +- `$className`: Полное имя класса, реализующего интерфейс `IDBItem`. + +**Возвращаемое значение:** Массив экземпляров указанных классов или false. + +#### Получение столбца (`GetCol()`) + +Выбирает конкретные столбцы и возвращает их в виде массива. + +**Параметры** + +- `$table`: Имя таблицы. +- `$column`: Выбираемый столбец. +- `$where`: Условия выборки (объект `ConditionBuilder`). + +**Возвращаемое значение:** Массив значений столбца или false. + +#### Получение одиночного значения (`GetValue()`) + +Выборка единственного значения (поле). + +**Параметры** + +- `$table`: Имя таблицы. +- `$column`: Столбец, содержащий искомое значение. +- `$where`: Условия выборки (объект `ConditionBuilder`). + +**Возвращаемое значение:** Значение выбранного поля или null. + +### 7. Подсчёт количества / существование записи + +#### Подсчет записей (`Count()`) + +Подсчитывает количество записей, соответствующих фильтру. + +**Параметры** + +- `$table`: Имя таблицы. +- `$where`: Условия подсчета (объект `ConditionBuilder`). + +**Возвращаемое значение:** Целочисленное значение числа записей или -1 в случае ошибки. + +#### Проверка существования записей (`IsExist()`) + +Проверяет наличие хотя бы одной записи по указанным критериям. + +**Параметры** + +- `$table`: Имя таблицы. +- `$where`: Условия фильтра (объект `ConditionBuilder`). + +**Возвращаемое значение:** true, если хотя бы одна запись найдена, иначе false. + +### 8. Обновления и удаление + +#### Обновление одной записи (`Update()`) + +Обновляет одно значение в таблице. + +**Параметры** + +- `$table`: Имя таблицы. +- `$item`: Объект, реализующий интерфейс `IDBItem`. + +**Возвращаемое значение:** true при успешном выполнении, false — в противном случае. + +#### Обновление нескольких записей (`UpdateMany()`) + +Массовое обновление записей. + +**Параметры** + +- `$table`: Имя таблицы. +- `...$items`: Множество объектов, реализующих интерфейс `IDBItem`. + +**Возвращаемое значение:** true при успешной массовой обработке, false — в случае ошибки. + +#### Удаление записей (`Delete()`) + +Удаляет записи по заданному критерию. + +**Параметры** + +- `$table`: Имя таблицы. +- `$where`: Критерии удаления (объект `ConditionBuilder`). + +**Возвращаемое значение:** true при успехе, false — в случае ошибки. + +### 9. Управление таблицами + +#### Проверка существования таблицы (`IsTableExist()`) + +Проверяет существование конкретной таблицы. + +**Параметр** + +- `$tableName`: Имя проверяемой таблицы. + +**Возвращаемое значение:** true, если таблица существует, false — если отсутствует. + +#### Создание таблицы (`CreateTable()`) + +Создает новую таблицу на основе структуры модели. + +**Параметры** + +- `$tableName`: Имя создаваемой таблицы. +- `$dbItemClass`: Класс модели, представляющий структуру таблицы. + +**Возвращаемое значение:** true при создании, false — в случае неудачи. + +#### Удаление таблицы (`DropTable()`) + +Удаляет таблицу из базы данных. + +**Параметр** + +- `$tableName`: Имя удаляемой таблицы. + +**Возвращаемое значение:** true при удачном удалении, false — в случае ошибки. + +--- + +### Примеры использования методов + +#### Пример №1: добавления новой записи: + +Предположим для примеров, что есть некоторый класс пользователя + +```php +use goodboyalex\php_db_components_pack\interfaces\IDBItem; + +class UserModel implements IDBItem { +... +} +``` +Добавим его в базу данных: + +```php +$table = 'users'; +$userData = new UserModel(); +$userData->setUsername('test_user')->setEmail('test@example.com'); +$result = $db->Insert($table, $userData); +if ($result !== false) { + echo "Пользователь успешно добавлен!"; +} +``` + +#### Пример №2: обновление данных: + +```php +// Допустим, мы хотим обновить email пользователя +$newEmail = 'new_email@example.com'; + +// $userData - это UserModel (полученная ранее из БД) + +// Обновим Email +$userData->setEmail($newEmail); + +if ($db->Update('users', $userData)) { + echo "Данные пользователя успешно обновлены."; +} +``` + +### Пример №3: Массовая вставка данных + +Допустим, вам нужно добавить несколько пользователей одним запросом: + +```php +use goodboyalex\php_db_components_pack\classes\Database; +use goodboyalex\php_db_components_pack\models\UserModel; + +// Предположим, что у вас уже инициализирован объект $db +$table = 'users'; + +// Массив объектов пользователей +$sources[] = new UserModel(['username' => 'Alice']); +$sources[] = new UserModel(['username' => 'Bob']); + +// Вставляем всех пользователей разом +$result = $db->InsertMany($table, ...$sources); + +if ($result !== false) { + foreach ($result as $insertedId) { + echo "Добавлен новый пользователь с ID: $insertedId\n"; + } +} else { + echo "Ошибка при массовом добавлении пользователей.\n"; +} +``` + +### Пример №4: Проверка существования пользователя по имени + +Вам нужно проверить, зарегистрирован ли пользователь с определенным именем в вашей базе данных: + +```php +use goodboyalex\php_db_components_pack\conditions\ConditionBuilder; + +// Настраиваем условие +$condition = new ConditionBuilder(); +$condition->addCondition('username', '=', 'JohnDoe'); + +// Проверяем наличие пользователя +$exists = $db->IsExist('users', $condition); + +if ($exists) { + echo "Пользователь JohnDoe уже зарегистрирован!\n"; +} else { + echo "Пользователь JohnDoe пока не зарегистрирован.\n"; +} +``` + +### Пример №5: Поиск списка пользователей старше определенного возраста + +Допустим, нам нужно выбрать всех пользователей старше 30 лет: + +```php +use goodboyalex\php_db_components_pack\conditions\ConditionBuilder; + +// Настройка условия +$condition = new ConditionBuilder(); +$condition->addCondition('age', '>=', 30); + +// Загружаем всех пользователей, соответствующих условию +$users = $db->GetRows('users', $condition, ['id', 'username'], '\\UserModel'); + +foreach ($users as $user) { + echo "Имя пользователя: {$user->getUsername()}, возраст: {$user->getAge()}\n"; +} +``` + +### Пример №6: Подсчет общего количества зарегистрированных пользователей + +Нужно посчитать общее число пользователей в базе данных: + +```php +use goodboyalex\php_db_components_pack\conditions\ConditionBuilder; + +// Используем пустое условие, чтобы считать всех пользователей +$condition = new ConditionBuilder(); + +// Подсчет количества пользователей +$count = $db->Count('users', $condition); + +echo "Всего зарегистрировано пользователей: $count\n"; +``` + +### Пример №7: Удаление устаревших пользователей + +Например, вы хотите удалить всех пользователей, чья активность была давно утрачена (предположим, пользователи с датой последнего входа больше месяца назад): + +```php +use goodboyalex\php_db_components_pack\conditions\ConditionBuilder; + +// Например, удаляем пользователей, не заходивших последний месяц +$lastMonthDate = date("Y-m-d H:i:s", strtotime('-1 month')); + +$condition = new ConditionBuilder(); +$condition->addCondition('last_login_date', '<=', $lastMonthDate); + +// Удаляем старых пользователей +if ($db->Delete('users', $condition)) { + echo "Устаревшие пользователи были успешно удалены.\n"; +} else { + echo "Ошибка при удалении устаревших пользователей.\n"; +} +``` + +Эти примеры демонстрируют широкий спектр возможностей, предоставляемых классом `Database`, позволяя эффективно управлять взаимодействием с базой данных. + +## Вывод + +Таким образом, этот класс предоставляет удобные инструменты для реализации большинства стандартных операций с базой +данных на уровне ORM-подхода. + +[На главную](../index.md) \ No newline at end of file diff --git a/help/index.md b/help/index.md new file mode 100644 index 0000000..c535cf7 --- /dev/null +++ b/help/index.md @@ -0,0 +1,16 @@ +# Добро пожаловать в справочное руководство по компонентам PHP DB COMPONENTS PACK! + +## Руководство актуально для версии v1.0 + +## Автор: Александр Бабаев + +### Выберете интересующий Вас раздел: + +### Базовое использование: + +- [Подготовка к использованию](basic_usage/usage_preparation.md) + +##### Описание интерфейсов, классов и перечислений: + +- [DBConfig](class_desc/DBConfig.md) +- [DBDriver](class_desc/DBDriver.md) \ No newline at end of file diff --git a/sources/classes/ConditionBuilder.php b/sources/classes/ConditionBuilder.php index 7de805a..faba0a9 100644 --- a/sources/classes/ConditionBuilder.php +++ b/sources/classes/ConditionBuilder.php @@ -174,8 +174,6 @@ $conditionItems[] = self::ParseCondition($key, [$condition]); } - //var_dump($conditionItems); - // Возвращаем группу условий return new ConditionGroup($operator, $conditionItems); } diff --git a/sources/classes/DBItemProperty.php b/sources/classes/DBItemProperty.php index 3a41cb1..c37d73a 100644 --- a/sources/classes/DBItemProperty.php +++ b/sources/classes/DBItemProperty.php @@ -31,9 +31,9 @@ public string $FieldName; /** - * @var DataBaseHeadItem $Column Информация об ячейке. + * @var DataBaseColumn $Column Информация об ячейке. */ - public DataBaseHeadItem $Column; + public DataBaseColumn $Column; /** * @var bool $IsIgnored Признак того, что свойство игнорируется при сохранении в / загрузке из БД. @@ -61,14 +61,14 @@ * @param string $name Имя свойства. * @param mixed|null $value Значение свойства (ещё не конвертированное!). * @param string $fieldName Имя поля в таблице БД. - * @param DataBaseHeadItem $column Информация об ячейке. + * @param DataBaseColumn $column Информация об ячейке. * @param bool $isIgnored Признак того, что свойство игнорируется при сохранении в / загрузке из БД. * @param callable|null $ConvertToDB Конвертер значения свойства в значение поля БД. * @param Closure|null $ConvertFromDB Конвертер значения поля БД в значение свойства. * @param Closure|null $Compare Функция сравнения значений свойства. */ public function __construct (string $name = '', mixed $value = null, string $fieldName = '', - DataBaseHeadItem $column = new DataBaseHeadItem(), bool $isIgnored = false, ?callable $ConvertToDB = null, + DataBaseColumn $column = new DataBaseColumn(), bool $isIgnored = false, ?callable $ConvertToDB = null, ?Closure $ConvertFromDB = null, ?Closure $Compare = null) { // Установка значений diff --git a/sources/classes/DataBaseHeadItem.php b/sources/classes/DataBaseColumn.php similarity index 99% rename from sources/classes/DataBaseHeadItem.php rename to sources/classes/DataBaseColumn.php index 24d56df..e12fe93 100644 --- a/sources/classes/DataBaseHeadItem.php +++ b/sources/classes/DataBaseColumn.php @@ -13,7 +13,7 @@ * @version 1.0 * @since 1.0 */ - final class DataBaseHeadItem + final class DataBaseColumn { /** * @var string $Name Имя колонки. diff --git a/sources/classes/DataBaseHeader.php b/sources/classes/DataBaseHeader.php deleted file mode 100644 index dc428dc..0000000 --- a/sources/classes/DataBaseHeader.php +++ /dev/null @@ -1,29 +0,0 @@ -Container = new ObjectArray(); - } - } \ No newline at end of file diff --git a/sources/classes/tm_drivers/MSSQLTableManager.php b/sources/classes/tm_drivers/MSSQLTableManager.php index ed061af..815401a 100644 --- a/sources/classes/tm_drivers/MSSQLTableManager.php +++ b/sources/classes/tm_drivers/MSSQLTableManager.php @@ -5,7 +5,10 @@ namespace goodboyalex\php_db_components_pack\classes\tm_drivers; - use goodboyalex\php_db_components_pack\classes\DataBaseHeader; + use goodboyalex\php_components_pack\classes\ObjectArray; + use goodboyalex\php_db_components_pack\classes\DataBaseColumn; + use goodboyalex\php_db_components_pack\enums\DBDriver; + use goodboyalex\php_db_components_pack\enums\DBType; use goodboyalex\php_db_components_pack\interfaces\ITableManager; use PDO; @@ -19,6 +22,20 @@ */ final class MSSQLTableManager implements ITableManager { + /** + * @var array $TypeConversation Массив типов. + */ + public array $TypeConversation { + get => [ + DBType::INT->name => 'INT', + DBType::FLOAT->name => 'DECIMAL(p,s)', + DBType::STRING->name => 'NVARCHAR', + DBType::BOOL->name => 'BIT', + DBType::DATE->name => 'DATETIME', + DBType::ARRAY->name => 'XML' + ]; + } + /** * @inheritDoc */ @@ -37,16 +54,104 @@ return $stmt->fetchColumn() === '1'; } - public function CreateTable (PDO $handle, string $tableName, DataBaseHeader $columns): bool + /** + * @inheritDoc + */ + public function CreateTable (PDO $handle, string $tableName, ObjectArray $columns): bool { - // TODO: Implement CreateTable() method. + // Если таблица $tableName уже существует + if ($this->IsTableExist($handle, $tableName)) + // - то прерываю + return false; - return false; + // Создаю массив столбцов + $colArray = []; + + // Для каждого переданного столбца + foreach ($columns as $column) + // - конвертирую его в строку и добавляю в массив + $colArray[] = $this->ParseColumn($column); + + // Конвертирую массив столбцов в строку + $columnsStr = implode(', ', $colArray); + + // Создаю SQL запрос + $sql = "CREATE TABLE [$tableName] ($columnsStr)"; + + + // Подготавливаю запрос + $stmt = $handle->prepare($sql); + + // Выполняю запрос + $stmt->execute(); + + // Возвращаю, существует ли теперь таблица + return $this->IsTableExist($handle, $tableName); } - public function DropTable (PDO $handle, string $tableName): bool + /** + * @inheritDoc + */ + public function ParseColumn (DataBaseColumn $column): string { - // TODO: Implement DropTable() method. - return false; + // Получаю тип данных + $dbType = $column->Type->Get(0); + + // Получаю размер типа данных + $dbTypeSize = $column->Type->Get(1) ?? 0; + + // Получаю SQL тип данных + $type = DBType::ToSQLType(DBDriver::MySQL, $dbType); + + // Если тип данных - строка + if ($dbType == DBType::STRING) + // - то добавляю размер + $type .= '(' . ($dbTypeSize == 0 ? 'MAX' : $dbTypeSize) . ')'; + + // Формирую начало результата + $result = "[$column->Name] $type"; + + // Если должно быть ненулевое значение + if ($column->IsNotNull) + // - то добавляю NOT NULL + $result .= ' NOT NULL'; + + // Если должно быть уникальное значение + if ($column->IsUnique) + // - то добавляю UNIQUE + $result .= ' UNIQUE'; + + // Если это первичный ключ + if ($column->IsPrimaryKey) + // - то добавляю PRIMARY KEY + $result .= ' PRIMARY KEY'; + + // Получаю связанную таблицу + $fkDefinitionTable = $column->ForeignWith->Get(0); + // - и столбец в ней + $fkDefinitionKey = $column->ForeignWith->Get(1); + + // Если связанная таблица и столбец определены + if (!($fkDefinitionTable == null || $fkDefinitionKey == null)) + // - то добавляю REFERENCES + $result .= " REFERENCES $fkDefinitionTable($fkDefinitionKey)"; + + // Если заданы проверки + if ($column->Check->Count() > 0) + // - то добавляю CHECK + $result .= " CHECK({$column->Check->Build()})"; + + // Если задано значение по умолчанию + if ($column->Default != null) + // - то добавляю DEFAULT + $result .= " DEFAULT '$column->Default'"; + + // Если это поле AutoIncrement + if ($column->IsAutoIncrement) + // - то добавляю AUTO_INCREMENT + $result .= ' IDENTITY(1,1)'; + + // Вывожу результат + return $result; } } \ No newline at end of file diff --git a/sources/classes/tm_drivers/MySQLTableManager.php b/sources/classes/tm_drivers/MySQLTableManager.php index ac256a1..1d9a781 100644 --- a/sources/classes/tm_drivers/MySQLTableManager.php +++ b/sources/classes/tm_drivers/MySQLTableManager.php @@ -5,7 +5,10 @@ namespace goodboyalex\php_db_components_pack\classes\tm_drivers; - use goodboyalex\php_db_components_pack\classes\DataBaseHeader; + use goodboyalex\php_components_pack\classes\ObjectArray; + use goodboyalex\php_db_components_pack\classes\DataBaseColumn; + use goodboyalex\php_db_components_pack\enums\DBDriver; + use goodboyalex\php_db_components_pack\enums\DBType; use goodboyalex\php_db_components_pack\interfaces\ITableManager; use PDO; @@ -19,6 +22,20 @@ */ final class MySQLTableManager implements ITableManager { + /** + * @var array $TypeConversation Массив типов. + */ + public array $TypeConversation { + get => [ + DBType::INT->name => 'INT', + DBType::FLOAT->name => 'DECIMAL', + DBType::STRING->name => 'VARCHAR', + DBType::BOOL->name => 'BOOLEAN', + DBType::DATE->name => 'TIMESTAMP', + DBType::ARRAY->name => 'JSON' + ]; + } + /** * @inheritDoc */ @@ -38,16 +55,103 @@ return $stmt->fetchColumn() > 0; } - public function CreateTable (PDO $handle, string $tableName, DataBaseHeader $columns): bool + /** + * @inheritDoc + */ + public function CreateTable (PDO $handle, string $tableName, ObjectArray $columns): bool { - // TODO: Implement CreateTable() method. + // Если таблица $tableName уже существует + if ($this->IsTableExist($handle, $tableName)) + // - то прерываю + return false; - return false; + // Создаю массив столбцов + $colArray = []; + + // Для каждого переданного столбца + foreach ($columns as $column) + // - конвертирую его в строку и добавляю в массив + $colArray[] = $this->ParseColumn($column); + + // Конвертирую массив столбцов в строку + $columnsStr = implode(', ', $colArray); + + // Создаю SQL запрос + $sql = "CREATE TABLE `$tableName` ($columnsStr)"; + + // Подготавливаю запрос + $stmt = $handle->prepare($sql); + + // Выполняю запрос + $stmt->execute(); + + // Возвращаю, существует ли теперь таблица + return $this->IsTableExist($handle, $tableName); } - public function DropTable (PDO $handle, string $tableName): bool + /** + * @inheritDoc + */ + public function ParseColumn (DataBaseColumn $column): string { - // TODO: Implement DropTable() method. - return false; + // Получаю тип данных + $dbType = $column->Type->Get(0); + + // Получаю размер типа данных + $dbTypeSize = $column->Type->Get(1) ?? 0; + + // Получаю SQL тип данных + $type = DBType::ToSQLType(DBDriver::MySQL, $dbType); + + // Если тип данных - строка + if ($dbType == DBType::STRING) + // - то добавляю размер + $type .= '(' . ($dbTypeSize == 0 ? 'MAX' : $dbTypeSize) . ')'; + + // Формирую начало результата + $result = "`$column->Name` $type"; + + // Если должно быть ненулевое значение + if ($column->IsNotNull) + // - то добавляю NOT NULL + $result .= ' NOT NULL'; + + // Если должно быть уникальное значение + if ($column->IsUnique) + // - то добавляю UNIQUE + $result .= ' UNIQUE'; + + // Если это первичный ключ + if ($column->IsPrimaryKey) + // - то добавляю PRIMARY KEY + $result .= ' PRIMARY KEY'; + + // Получаю связанную таблицу + $fkDefinitionTable = $column->ForeignWith->Get(0); + // - и столбец в ней + $fkDefinitionKey = $column->ForeignWith->Get(1); + + // Если связанная таблица и столбец определены + if (!($fkDefinitionTable == null || $fkDefinitionKey == null)) + // - то добавляю REFERENCES + $result .= " REFERENCES $fkDefinitionTable($fkDefinitionKey)"; + + // Если заданы проверки + if ($column->Check->Count() > 0) + // - то добавляю CHECK + $result .= " CHECK({$column->Check->Build()})"; + + // Если задано значение по умолчанию + if ($column->Default != null) + // - то добавляю DEFAULT + $result .= " DEFAULT '$column->Default'"; + + // Если это поле AutoIncrement + if ($column->IsAutoIncrement) + // - то добавляю AUTO_INCREMENT + $result .= ' AUTO_INCREMENT'; + + // Вывожу результат + return $result; } } \ No newline at end of file diff --git a/sources/classes/tm_drivers/OracleDBTableManager.php b/sources/classes/tm_drivers/OracleDBTableManager.php index 89582ff..3c4828d 100644 --- a/sources/classes/tm_drivers/OracleDBTableManager.php +++ b/sources/classes/tm_drivers/OracleDBTableManager.php @@ -5,9 +5,13 @@ namespace goodboyalex\php_db_components_pack\classes\tm_drivers; - use goodboyalex\php_db_components_pack\classes\DataBaseHeader; + use goodboyalex\php_components_pack\classes\ObjectArray; + use goodboyalex\php_db_components_pack\classes\DataBaseColumn; + use goodboyalex\php_db_components_pack\enums\DBDriver; + use goodboyalex\php_db_components_pack\enums\DBType; use goodboyalex\php_db_components_pack\interfaces\ITableManager; use PDO; + use PDOException; /** * Система менеджмента таблицами базы данных Oracle DB. @@ -19,6 +23,20 @@ */ final class OracleDBTableManager implements ITableManager { + /** + * @var array $TypeConversation Массив типов. + */ + public array $TypeConversation { + get => [ + DBType::INT->name => 'NUMBER', + DBType::FLOAT->name => 'FLOAT', + DBType::STRING->name => 'NVARCHAR2', + DBType::BOOL->name => 'NUMBER(1)', + DBType::DATE->name => 'DATE', + DBType::ARRAY->name => 'CLOB' + ]; + } + /** * @inheritDoc */ @@ -37,16 +55,109 @@ return $stmt->fetchColumn() > 0; } - public function CreateTable (PDO $handle, string $tableName, DataBaseHeader $columns): bool + /** + * @inheritDoc + */ + public function CreateTable (PDO $handle, string $tableName, ObjectArray $columns): bool { - // TODO: Implement CreateTable() method. + // Если таблица $tableName уже существует + if ($this->IsTableExist($handle, $tableName)) + // - то прерываю + return false; - return false; + // Создаю массив столбцов + $colArray = []; + + // Для каждого переданного столбца + foreach ($columns as $column) + // - конвертирую его в строку и добавляю в массив + $colArray[] = $this->ParseColumn($column); + + // Конвертирую массив столбцов в строку + $columnsStr = implode(', ', $colArray); + + // Создаю SQL запрос + $sql = "CREATE TABLE \"$tableName\" ($columnsStr)"; + + try { + // Подготавливаю запрос + $stmt = $handle->prepare($sql); + + // Выполняю запрос + $stmt->execute(); + + // Возвращаю, существует ли теперь таблица + return $this->IsTableExist($handle, $tableName); + } + catch (PDOException) { + // - в случае ошибки вывожу FALSE + return false; + } } - public function DropTable (PDO $handle, string $tableName): bool + /** + * @inheritDoc + */ + public function ParseColumn (DataBaseColumn $column): string { - // TODO: Implement DropTable() method. - return false; + // Получаю тип данных + $dbType = $column->Type->Get(0); + + // Получаю размер типа данных + $dbTypeSize = $column->Type->Get(1) ?? 0; + + // Получаю SQL тип данных + $type = DBType::ToSQLType(DBDriver::MySQL, $dbType); + + // Если тип данных - строка + if ($dbType == DBType::STRING) + // - то добавляю размер + $type .= '(' . ($dbTypeSize == 0 ? 'MAX' : $dbTypeSize) . ')'; + + // Формирую начало результата + $result = "$column->Name $type"; + + // Если должно быть ненулевое значение + if ($column->IsNotNull) + // - то добавляю NOT NULL + $result .= ' NOT NULL'; + + // Если должно быть уникальное значение + if ($column->IsUnique) + // - то добавляю UNIQUE + $result .= ' UNIQUE'; + + // Если это первичный ключ + if ($column->IsPrimaryKey) + // - то добавляю PRIMARY KEY + $result .= ' PRIMARY KEY'; + + // Получаю связанную таблицу + $fkDefinitionTable = $column->ForeignWith->Get(0); + // - и столбец в ней + $fkDefinitionKey = $column->ForeignWith->Get(1); + + // Если связанная таблица и столбец определены + if (!($fkDefinitionTable == null || $fkDefinitionKey == null)) + // - то добавляю REFERENCES + $result .= " REFERENCES $fkDefinitionTable($fkDefinitionKey)"; + + // Если заданы проверки + if ($column->Check->Count() > 0) + // - то добавляю CHECK + $result .= " CHECK({$column->Check->Build()})"; + + // Если задано значение по умолчанию + if ($column->Default != null) + // - то добавляю DEFAULT + $result .= " DEFAULT '$column->Default'"; + + // Если это поле AutoIncrement + if ($column->IsAutoIncrement) + // - то добавляю AUTO_INCREMENT + $result .= ' GENERATED BY DEFAULT AS IDENTITY'; + + // Вывожу результат + return $result; } } \ No newline at end of file diff --git a/sources/classes/tm_drivers/PostgreSQLTableManager.php b/sources/classes/tm_drivers/PostgreSQLTableManager.php index fdc7916..8b1a110 100644 --- a/sources/classes/tm_drivers/PostgreSQLTableManager.php +++ b/sources/classes/tm_drivers/PostgreSQLTableManager.php @@ -5,9 +5,13 @@ namespace goodboyalex\php_db_components_pack\classes\tm_drivers; - use goodboyalex\php_db_components_pack\classes\DataBaseHeader; + use goodboyalex\php_components_pack\classes\ObjectArray; + use goodboyalex\php_db_components_pack\classes\DataBaseColumn; + use goodboyalex\php_db_components_pack\enums\DBDriver; + use goodboyalex\php_db_components_pack\enums\DBType; use goodboyalex\php_db_components_pack\interfaces\ITableManager; use PDO; + use PDOException; /** * Система менеджмента таблицами базы данных PostgreSQL. @@ -19,6 +23,20 @@ */ final class PostgreSQLTableManager implements ITableManager { + /** + * @var array $TypeConversation Массив типов. + */ + public array $TypeConversation { + get => [ + DBType::INT->name => 'INTEGER', + DBType::FLOAT->name => 'NUMERIC', + DBType::STRING->name => 'TEXT', + DBType::BOOL->name => 'BOOL', + DBType::DATE->name => 'TIMESTAMPTZ', + DBType::ARRAY->name => 'JSONB' + ]; + } + /** * @inheritDoc */ @@ -41,16 +59,109 @@ return $stmt->fetchColumn() === 'true'; } - public function CreateTable (PDO $handle, string $tableName, DataBaseHeader $columns): bool + /** + * @inheritDoc + */ + public function CreateTable (PDO $handle, string $tableName, ObjectArray $columns): bool { - // TODO: Implement CreateTable() method. + // Если таблица $tableName уже существует + if ($this->IsTableExist($handle, $tableName)) + // - то прерываю + return false; - return false; + // Создаю массив столбцов + $colArray = []; + + // Для каждого переданного столбца + foreach ($columns as $column) + // - конвертирую его в строку и добавляю в массив + $colArray[] = $this->ParseColumn($column); + + // Конвертирую массив столбцов в строку + $columnsStr = implode(', ', $colArray); + + // Создаю SQL запрос + $sql = "CREATE TABLE \"$tableName\" ($columnsStr)"; + + try { + // Подготавливаю запрос + $stmt = $handle->prepare($sql); + + // Выполняю запрос + $stmt->execute(); + + // Возвращаю, существует ли теперь таблица + return $this->IsTableExist($handle, $tableName); + } + catch (PDOException) { + // - в случае ошибки вывожу FALSE + return false; + } } - public function DropTable (PDO $handle, string $tableName): bool + /** + * @inheritDoc + */ + public function ParseColumn (DataBaseColumn $column): string { - // TODO: Implement DropTable() method. - return false; + // Получаю тип данных + $dbType = $column->Type->Get(0); + + // Получаю размер типа данных + $dbTypeSize = $column->Type->Get(1) ?? 0; + + // Получаю SQL тип данных + $type = DBType::ToSQLType(DBDriver::MySQL, $dbType); + + // Если тип данных - строка + if ($dbType == DBType::STRING) + // - то добавляю размер + $type .= '(' . ($dbTypeSize == 0 ? 'MAX' : $dbTypeSize) . ')'; + + // Формирую начало результата + $result = "\"$column->Name\" $type"; + + // Если должно быть ненулевое значение + if ($column->IsNotNull) + // - то добавляю NOT NULL + $result .= ' NOT NULL'; + + // Если должно быть уникальное значение + if ($column->IsUnique) + // - то добавляю UNIQUE + $result .= ' UNIQUE'; + + // Если это первичный ключ + if ($column->IsPrimaryKey) + // - то добавляю PRIMARY KEY + $result .= ' PRIMARY KEY'; + + // Получаю связанную таблицу + $fkDefinitionTable = $column->ForeignWith->Get(0); + // - и столбец в ней + $fkDefinitionKey = $column->ForeignWith->Get(1); + + // Если связанная таблица и столбец определены + if (!($fkDefinitionTable == null || $fkDefinitionKey == null)) + // - то добавляю REFERENCES + $result .= " REFERENCES \"$fkDefinitionTable\"(\"$fkDefinitionKey\")"; + + // Если заданы проверки + if ($column->Check->Count() > 0) + // - то добавляю CHECK + $result .= " CHECK({$column->Check->Build()})"; + + // Если задано значение по умолчанию + if ($column->Default != null) + // - то добавляю DEFAULT + $result .= " DEFAULT '$column->Default'"; + + // Если это поле AutoIncrement + if ($column->IsAutoIncrement) + // - то добавляю AUTO_INCREMENT + $result .= ' SERIAL'; + + // Вывожу результат + return $result; } } \ No newline at end of file diff --git a/sources/classes/tm_drivers/SQLiteTableManager.php b/sources/classes/tm_drivers/SQLiteTableManager.php index f57b32d..30d496f 100644 --- a/sources/classes/tm_drivers/SQLiteTableManager.php +++ b/sources/classes/tm_drivers/SQLiteTableManager.php @@ -5,9 +5,13 @@ namespace goodboyalex\php_db_components_pack\classes\tm_drivers; - use goodboyalex\php_db_components_pack\classes\DataBaseHeader; + use goodboyalex\php_components_pack\classes\ObjectArray; + use goodboyalex\php_db_components_pack\classes\DataBaseColumn; + use goodboyalex\php_db_components_pack\enums\DBDriver; + use goodboyalex\php_db_components_pack\enums\DBType; use goodboyalex\php_db_components_pack\interfaces\ITableManager; use PDO; + use PDOException; /** * Система менеджмента таблицами базы данных SQLite. @@ -19,6 +23,20 @@ */ final class SQLiteTableManager implements ITableManager { + /** + * @var array $TypeConversation Массив типов. + */ + public array $TypeConversation { + get => [ + DBType::INT->name => 'INTEGER', + DBType::FLOAT->name => 'REAL', + DBType::STRING->name => 'TEXT', + DBType::BOOL->name => 'BOOLEAN', + DBType::DATE->name => 'DATETIME', + DBType::ARRAY->name => 'TEXT' + ]; + } + /** * @inheritDoc */ @@ -37,16 +55,99 @@ return $stmt->fetchColumn() > 0; } - public function CreateTable (PDO $handle, string $tableName, DataBaseHeader $columns): bool + /** + * @inheritDoc + */ + public function CreateTable (PDO $handle, string $tableName, ObjectArray $columns): bool { - // TODO: Implement CreateTable() method. + // Если таблица $tableName уже существует + if ($this->IsTableExist($handle, $tableName)) + // - то прерываю + return false; - return false; + // Создаю массив столбцов + $colArray = []; + + // Для каждого переданного столбца + foreach ($columns as $column) + // - конвертирую его в строку и добавляю в массив + $colArray[] = $this->ParseColumn($column); + + // Конвертирую массив столбцов в строку + $columnsStr = implode(', ', $colArray); + + // Создаю SQL запрос + $sql = "CREATE TABLE IF NOT EXISTS \"$tableName\" ($columnsStr)"; + + try { + // Подготавливаю запрос + $stmt = $handle->prepare($sql); + + // Выполняю запрос + $stmt->execute(); + + // Возвращаю, существует ли теперь таблица + return $this->IsTableExist($handle, $tableName); + } + catch (PDOException) { + // - в случае ошибки вывожу FALSE + return false; + } } - public function DropTable (PDO $handle, string $tableName): bool + /** + * @inheritDoc + */ + public function ParseColumn (DataBaseColumn $column): string { - // TODO: Implement DropTable() method. - return false; + // Получаю тип данных + $dbType = $column->Type->Get(0); + + // Получаю размер типа данных + $dbTypeSize = $column->Type->Get(1) ?? 0; + + // Получаю SQL тип данных + $type = DBType::ToSQLType(DBDriver::MySQL, $dbType); + + // Если тип данных - строка + if ($dbType == DBType::STRING) + // - то добавляю размер + $type .= '(' . ($dbTypeSize == 0 ? 'MAX' : $dbTypeSize) . ')'; + + // Формирую начало результата + $result = "$column->Name $type"; + + // Если должно быть ненулевое значение + if ($column->IsNotNull) + // - то добавляю NOT NULL + $result .= ' NOT NULL'; + + // Если должно быть уникальное значение + if ($column->IsUnique) + // - то добавляю UNIQUE + $result .= ' UNIQUE'; + + // Если это первичный ключ + if ($column->IsPrimaryKey) + // - то добавляю PRIMARY KEY + $result .= ' PRIMARY KEY'; + + // Если заданы проверки + if ($column->Check->Count() > 0) + // - то добавляю CHECK + $result .= " CHECK({$column->Check->Build()})"; + + // Если задано значение по умолчанию + if ($column->Default != null) + // - то добавляю DEFAULT + $result .= " DEFAULT '$column->Default'"; + + // Если это поле AutoIncrement + if ($column->IsAutoIncrement) + // - то добавляю AUTO_INCREMENT + $result .= ' AUTOINCREMENT'; + + // Вывожу результат + return $result; } } \ No newline at end of file diff --git a/sources/enums/DBOperation.php b/sources/enums/DBOperation.php index cb8a674..6714586 100644 --- a/sources/enums/DBOperation.php +++ b/sources/enums/DBOperation.php @@ -42,4 +42,14 @@ * Операция подсчета количества. */ case Count = 4; + + /** + * Операция создания таблицы в базе данных. + */ + case CreateTable = 5; + + /** + * Операция удаления таблицы в базе данных. + */ + case DropTable = 6; } \ No newline at end of file diff --git a/sources/enums/DBType.php b/sources/enums/DBType.php index 2ca5a91..f57d5b4 100644 --- a/sources/enums/DBType.php +++ b/sources/enums/DBType.php @@ -3,6 +3,11 @@ namespace goodboyalex\php_db_components_pack\enums; use goodboyalex\php_components_pack\traits\EnumExtensionsTrait; + use goodboyalex\php_db_components_pack\classes\tm_drivers\MSSQLTableManager; + use goodboyalex\php_db_components_pack\classes\tm_drivers\MySQLTableManager; + use goodboyalex\php_db_components_pack\classes\tm_drivers\OracleDBTableManager; + use goodboyalex\php_db_components_pack\classes\tm_drivers\PostgreSQLTableManager; + use goodboyalex\php_db_components_pack\classes\tm_drivers\SQLiteTableManager; /** * Перечисление типов в БД. @@ -46,4 +51,27 @@ * Массив/объект. */ case ARRAY = 5; + + /** + * Переводит значение из типа DBType в тип, пригодный в СУБД. + * + * @param DBDriver $driver Тип драйвера СУБД. + * @param DBType $value Тип данных. + * + * @return string SQL-тип. + */ + public static function ToSQLType (DBDriver $driver, DBType $value): string + { + // Получаю систему управления таблицами БД + $dbDrv = match ($driver) { + DBDriver::MySQL => new MySQLTableManager(), + DBDriver::MSSQL => new MSSQLTableManager(), + DBDriver::PostgreSQL => new PostgreSQLTableManager(), + DBDriver::OracleDB => new OracleDBTableManager(), + DBDriver::SQLite => new SQLiteTableManager() + }; + + // Получаю тип + return $dbDrv->TypeConversation[$value->GetValue()]; + } } \ No newline at end of file diff --git a/sources/interfaces/ITableManager.php b/sources/interfaces/ITableManager.php index b7ef523..65d3e9b 100644 --- a/sources/interfaces/ITableManager.php +++ b/sources/interfaces/ITableManager.php @@ -2,7 +2,8 @@ namespace goodboyalex\php_db_components_pack\interfaces; - use goodboyalex\php_db_components_pack\classes\DataBaseHeader; + use goodboyalex\php_components_pack\classes\ObjectArray; + use goodboyalex\php_db_components_pack\classes\DataBaseColumn; use PDO; /** @@ -15,6 +16,13 @@ */ interface ITableManager { + /** + * @var array $TypeConversation Таблица соответствий типов данных PHP и соответствующего драйвера СУБД. + */ + public array $TypeConversation { + get; + } + /** * Проверяет существование таблицы в базе данных. * @@ -30,19 +38,18 @@ * * @param PDO $handle Представляет соединение между PHP и сервером базы данных. * @param string $tableName Имя таблицы. - * @param DataBaseHeader $columns Колонки таблицы. + * @param ObjectArray $columns Колонки таблицы. * * @return bool Возвращает true, если таблица успешно создана, иначе возвращает false. */ - public function CreateTable (PDO $handle, string $tableName, DataBaseHeader $columns): bool; + public function CreateTable (PDO $handle, string $tableName, ObjectArray $columns): bool; /** - * Удаляет таблицу из базы данных. + * Разбирает столбец для SQL-запроса создания. * - * @param PDO $handle Представляет соединение между PHP и сервером базы данных. - * @param string $tableName Имя таблицы. + * @param DataBaseColumn $column Столбец таблицы. * - * @return bool Возвращает true, если таблица успешно удалена, иначе возвращает false. + * @return string SQL-представление столбца. */ - public function DropTable (PDO $handle, string $tableName): bool; + public function ParseColumn (DataBaseColumn $column): string; } \ No newline at end of file diff --git a/sources/models/DBConfig.php b/sources/models/DBConfig.php index 8f65f10..404f236 100644 --- a/sources/models/DBConfig.php +++ b/sources/models/DBConfig.php @@ -10,7 +10,7 @@ * Модель параметров базы данных. * * @author Александр Бабаев - * @package php_components_pack + * @package php_db_components_pack * @version 1.0 * @since 1.0 */ diff --git a/sources/traits/Database/DatabaseSpecial.php b/sources/traits/Database/DatabaseSpecial.php index 1556776..e3bd42e 100644 --- a/sources/traits/Database/DatabaseSpecial.php +++ b/sources/traits/Database/DatabaseSpecial.php @@ -21,7 +21,7 @@ use goodboyalex\php_db_components_pack\attributes\PrimaryKey; use goodboyalex\php_db_components_pack\attributes\Unique; use goodboyalex\php_db_components_pack\classes\ConditionBuilder; - use goodboyalex\php_db_components_pack\classes\DataBaseHeadItem; + use goodboyalex\php_db_components_pack\classes\DataBaseColumn; use goodboyalex\php_db_components_pack\classes\DBItemProperty; use goodboyalex\php_db_components_pack\enums\DBOperation; use goodboyalex\php_db_components_pack\enums\DBType; @@ -219,7 +219,7 @@ $isAutoIncrement = $aiAttr !== null; // - создаю заголовок - $columnHeader = new DataBaseHeadItem($fieldName, $dataType, $isNotNull, $isUnique, $isPrimary, + $columnHeader = new DataBaseColumn($fieldName, $dataType, $isNotNull, $isUnique, $isPrimary, $foreignWith, $checkFunc, $default, $isAutoIncrement); diff --git a/sources/traits/Database/DatabaseTableManagement.php b/sources/traits/Database/DatabaseTableManagement.php index 80f3b3a..d242e5c 100644 --- a/sources/traits/Database/DatabaseTableManagement.php +++ b/sources/traits/Database/DatabaseTableManagement.php @@ -6,12 +6,17 @@ namespace goodboyalex\php_db_components_pack\traits\Database; + use Exception; + use goodboyalex\php_components_pack\classes\ObjectArray; + use goodboyalex\php_db_components_pack\classes\DBItemProperty; use goodboyalex\php_db_components_pack\classes\tm_drivers\MSSQLTableManager; use goodboyalex\php_db_components_pack\classes\tm_drivers\MySQLTableManager; use goodboyalex\php_db_components_pack\classes\tm_drivers\OracleDBTableManager; use goodboyalex\php_db_components_pack\classes\tm_drivers\PostgreSQLTableManager; use goodboyalex\php_db_components_pack\classes\tm_drivers\SQLiteTableManager; use goodboyalex\php_db_components_pack\enums\DBDriver; + use goodboyalex\php_db_components_pack\enums\DBOperation; + use goodboyalex\php_db_components_pack\interfaces\IDBItem; use PDO; /** @@ -46,4 +51,124 @@ // Проверяю существование таблицы, вывожу результат return $dbDrv->isTableExist($this->DataBaseHandle, $tableName); } + + /** + * Создаёт новую таблицу. + * + * @param string $tableName Имя таблицы. + * @param string $dbItemClass Класс моделей, которых будет представлять эта таблица. + * + * @return bool Результат создания: true, если таблица создана и false, если + * произошла ошибка. + */ + public function CreateTable (string $tableName, string $dbItemClass): bool + { + // Создаю экземпляр класса + $instance = new $dbItemClass(); + + // Проверяю, что он реализует интерфейс IDBItem + if (!$instance instanceof IDBItem) + // - если нет, ошибка + return false; + + // Получаю свойства класса + $properties = self::GetProperties($instance, DBOperation::CreateTable); + + // Создаю массив столбцов + $columns = new ObjectArray(); + + /** + * Для каждого свойства... + * + * @var DBItemProperty $property Свойство. + */ + foreach ($properties as $property) + // - добавляю его столбцы в массив столбцов + $columns->Add($property->Column); + + // Получаю систему управления таблицами БД + $dbDrv = match ($this->Config->Driver) { + DBDriver::MySQL => new MySQLTableManager(), + DBDriver::MSSQL => new MSSQLTableManager(), + DBDriver::PostgreSQL => new PostgreSQLTableManager(), + DBDriver::OracleDB => new OracleDBTableManager(), + DBDriver::SQLite => new SQLiteTableManager() + }; + + try { + // Активирую транзакцию + $this->InitTransaction(); + + // Создаю таблицу и возвращаю результат + $result = $dbDrv->CreateTable($this->DataBaseHandle, $tableName, $columns); + + // Отправляю данные в БД + $this->Commit(); + + // Возвращаю результат + return $result; + } + catch (Exception $exception) { + // - в случае ошибки, пытаюсь откатиться назад + $this->RollBack(); + + // - обрабатываю исключение + $this->HandleException($exception, false); + + // - возвращаю провал + return false; + } + } + + /** + * Удаляет таблицу. + * + * @param string $tableName Имя удаляемой таблицы. + * + * @return bool Результат удаления: true - таблица удалена, false - произошла + * неизвестная ошибка при удалении. + */ + public function DropTable (string $tableName): bool + { + // Если таблицы не существует или она уже удалена + if (!$this->IsTableExist($tableName)) + // - то возвращаем true + return true; + + // SQL-запрос + $sql = "DROP TABLE dbo.`$tableName`"; + + // Инициализирую транзакцию + $this->InitTransaction(); + + // Выполняю SQL-запрос удаления + $result = $this->Execute($sql); + + // Если неудачно + if ($result === false) { + // - то откатываю изменения + $this->RollBack(); + + // - возвращаю провал + return false; + } + + try { + // Пытаюсь отправить изменения + $this->Commit(); + } + catch (Exception $exception) { + // - в случае ошибки, откатываю изменения + $this->RollBack(); + + // - описываю ошибку + $this->HandleException($exception, false); + + // - возвращаю провал + return false; + } + + // Возвращаю, существует ли теперь таблица + return $this->IsTableExist($tableName); + } } \ No newline at end of file diff --git a/sources/traits/Database/DatabaseUpdate.php b/sources/traits/Database/DatabaseUpdate.php index 558fb44..c1b926a 100644 --- a/sources/traits/Database/DatabaseUpdate.php +++ b/sources/traits/Database/DatabaseUpdate.php @@ -37,7 +37,7 @@ $properties = self::GetProperties($item, DBOperation::Update); // Получаю первичные ключи объекта - $primaryKeys = $properties->GetRows(fn (DBItemProperty $property): bool => $property->IsPrimaryKey); + $primaryKeys = $properties->GetRows(fn (DBItemProperty $property): bool => $property->Column->IsPrimaryKey); // Создаю условие по первичным ключам (оно же и WHERE для обновления) $where = new ConditionBuilder();