20250729
This commit is contained in:
248
sources/traits/Database/DatabaseSpecial.php
Normal file
248
sources/traits/Database/DatabaseSpecial.php
Normal file
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @noinspection SqlNoDataSourceInspection
|
||||
*/
|
||||
|
||||
namespace goodboyalex\php_db_components_pack\traits\Database;
|
||||
|
||||
use Exception;
|
||||
use goodboyalex\php_components_pack\exceptions\TypeException;
|
||||
use goodboyalex\php_components_pack\extensions\TypeExtension;
|
||||
use goodboyalex\php_db_components_pack\interfaces\IDBItem;
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
* Трейт для функций поддержки для работы с базой данных.
|
||||
*
|
||||
* @author Александр Бабаев
|
||||
* @package php_components_pack
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
* @see PDO
|
||||
*/
|
||||
trait DatabaseSpecial
|
||||
{
|
||||
/**
|
||||
* Добавляет параметр в массив.
|
||||
*
|
||||
* @param array $array Массив.
|
||||
* @param string $key Имя параметра.
|
||||
* @param mixed $value Значение параметра.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function AddArrayItem (array &$array, string $key, mixed $value): void
|
||||
{
|
||||
// Если ключ параметра начинается с ":"
|
||||
if ($key[0] == ":")
|
||||
// - то сразу добавляем его в результирующий массив
|
||||
$array[$key] = $value;
|
||||
else
|
||||
// - в противном случае, предварительно добавим в имя ключа ":"
|
||||
$array[':' . $key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Обрабатывает исключение.
|
||||
*
|
||||
* @param Exception $exception Исключение.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function HandleException (Exception $exception): void
|
||||
{
|
||||
// Выбираю обработчик исключений
|
||||
$onException = $this->OnException ?? fn (Exception $e) => die($e->getMessage());
|
||||
|
||||
// Выполняю обработчик исключений
|
||||
$onException($exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготавливает массив параметров
|
||||
*
|
||||
* @param IDBItem $source Объект со свойствами.
|
||||
* @param bool $withId Добавлять ли id в массив.
|
||||
* @param array $options Опции.
|
||||
*
|
||||
* @return array|false Подготовленный массив параметров или false в случае ошибки
|
||||
*/
|
||||
private function PrepareParamsArray (IDBItem $source, bool $withId = true, array $options = []): array|false
|
||||
{
|
||||
// Создаём результирующий массив
|
||||
$result = [];
|
||||
|
||||
// Если есть игнорируемые или разрешенные свойства
|
||||
if (!(count($options['ignore']) == 0 && count($options['allow']) == 0))
|
||||
// -- то для каждого игнорируемого свойства
|
||||
foreach ($options['ignored'] as $ignoredProperty)
|
||||
// --- и если оно есть в массиве разрешенных
|
||||
if (in_array($ignoredProperty, $options['allowed']))
|
||||
// ---- то исключаю его из массива разрешенных
|
||||
unset($options['allowed'][array_search($ignoredProperty, $options['allowed'])]);
|
||||
|
||||
// Получаю массив свойств
|
||||
$properties = $source->ToSQL($withId);
|
||||
|
||||
// Для каждого элемента массива
|
||||
foreach ($properties as $name => $value) {
|
||||
// - если свойство игнорируется
|
||||
if (in_array($name, $options['ignored']))
|
||||
// -- пропускаю
|
||||
continue;
|
||||
|
||||
// - если свойство не разрешено
|
||||
if (count($options['allowed']) > 0 && !in_array($name, $options['allowed']))
|
||||
// -- пропускаю
|
||||
continue;
|
||||
|
||||
// - если свойство является объектом
|
||||
if (is_object($source->$name)) {
|
||||
try {
|
||||
// -- пытаюсь преобразовать его в массив
|
||||
self::AddArrayItem($result, $name, json_encode(TypeExtension::ToArray($source->$name),
|
||||
JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
|
||||
}
|
||||
catch (TypeException) {
|
||||
// -- если не получилось, то сериализую его
|
||||
self::AddArrayItem($result, $name,
|
||||
json_encode($source->$name, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
|
||||
}
|
||||
|
||||
// -- пропускаю
|
||||
continue;
|
||||
}
|
||||
|
||||
// - если свойство является массивом
|
||||
if (is_array($source->$name)) {
|
||||
// -- сериализую его
|
||||
self::AddArrayItem($result, $name, json_encode($source->$name, JSON_UNESCAPED_UNICODE |
|
||||
JSON_PRETTY_PRINT));
|
||||
|
||||
// -- пропускаю
|
||||
continue;
|
||||
}
|
||||
|
||||
// - иначе просто добавляю свойство в массив
|
||||
self::AddArrayItem($result, $name, $source->$name);
|
||||
}
|
||||
|
||||
// Вывожу результирующий массив
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготавливает массив столбцов для использования в базе данных
|
||||
*
|
||||
* @param array $columns Массив колонок.
|
||||
*
|
||||
* @return array Массив преобразованных колонок.
|
||||
*/
|
||||
private function PrepareColumn (array $columns): array
|
||||
{
|
||||
return array_map(function ($item)
|
||||
{
|
||||
// Результирующая строка
|
||||
$result = "";
|
||||
|
||||
// Если длинна строки > 0
|
||||
if (strlen($item) > 0) {
|
||||
// - первый символ
|
||||
$firstLetter = substr($item, 0, 1);
|
||||
|
||||
// - последний символ
|
||||
$lastLetter = substr($item, -1);
|
||||
|
||||
// - если первый символ не $this->DBSignOpen
|
||||
if ($firstLetter !== $this->DBSignOpen)
|
||||
// -- то добавляем
|
||||
$result .= $this->DBSignOpen;
|
||||
|
||||
// - добавляем строку
|
||||
$result .= $item;
|
||||
|
||||
// - если последний символ не $this->DBSignClose
|
||||
if ($lastLetter !== $this->DBSignClose)
|
||||
// -- то добавляем
|
||||
$result .= $this->DBSignClose;
|
||||
}
|
||||
|
||||
// Возвращаем результат
|
||||
return $result;
|
||||
}, $columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Генерирует SQL запрос выборки строк.
|
||||
*
|
||||
* @param string $table Имя таблицы
|
||||
* @param array $columns Колонки, которые нужно включить в запрос
|
||||
* @param array $where Параметры выборки
|
||||
* @param array $params Параметры и их значения
|
||||
*
|
||||
* @return string SQL-запрос
|
||||
*/
|
||||
private function PrepareSQLForRowsQuery (string $table, array $columns = [], array $where = [],
|
||||
array &$params = []): string
|
||||
{
|
||||
// Очищаю параметры
|
||||
$params = [];
|
||||
|
||||
// Строковая интерпретация массива условий
|
||||
$sql_where = $this->PrepareQueryWhere($where, $params);
|
||||
|
||||
// Колонки
|
||||
$sql_columns = count($columns) > 0 ? implode(', ', $this->PrepareColumn($columns)) : "*";
|
||||
|
||||
// Создаю запрос
|
||||
$sql = "SELECT $sql_columns FROM $this->DBSignOpen$table$this->DBSignClose";
|
||||
|
||||
// Если заданы where-параметры
|
||||
if (count($where) > 0) {
|
||||
// - то добавляю их
|
||||
$sql .= " WHERE $sql_where";
|
||||
}
|
||||
|
||||
// Возвращаю запрос
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Готовит выражение для WHERE-запроса
|
||||
*
|
||||
* @param array $where Массив условий
|
||||
* @param array $params Очищенные параметры
|
||||
*
|
||||
* @return string Строка WHERE-запроса
|
||||
*/
|
||||
private function PrepareQueryWhere (array $where, array &$params): string
|
||||
{
|
||||
// Очищаю параметры
|
||||
$params = [];
|
||||
|
||||
// Задаю результат
|
||||
$result = "";
|
||||
|
||||
// Если массив условий не пуст
|
||||
if (count($where) > 0) {
|
||||
// - то для каждого условия
|
||||
foreach ($where as $key => $value) {
|
||||
// -- получаю ключ 100%-но без ":" в начале
|
||||
$where_key = $key[0] == ":" ? substr($key, 1) : $key;
|
||||
|
||||
// -- добавляю префикс для 2 или более итерации
|
||||
$prefix = $result == "" ? "" : " AND ";
|
||||
|
||||
// -- добавляю данные в $sql_where
|
||||
$result .= $prefix . $this->DBSignOpen . $where_key . $this->DBSignClose . " = :" . $where_key;
|
||||
|
||||
// -- добавляю данные в параметры
|
||||
$params[$where_key] = "$value";
|
||||
}
|
||||
}
|
||||
|
||||
// Вывожу результат
|
||||
return $result;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user