20250802-1
This commit is contained in:
@@ -7,17 +7,18 @@
|
||||
namespace goodboyalex\php_db_components_pack\traits\Database;
|
||||
|
||||
use Exception;
|
||||
use goodboyalex\php_components_pack\classes\ObjectArray;
|
||||
use goodboyalex\php_db_components_pack\attributes\ConvertToDB;
|
||||
use goodboyalex\php_db_components_pack\attributes\FieldName;
|
||||
use goodboyalex\php_db_components_pack\attributes\IgnoredInDB;
|
||||
use goodboyalex\php_db_components_pack\attributes\PrimaryKey;
|
||||
use goodboyalex\php_db_components_pack\classes\ConditionBuilder;
|
||||
use goodboyalex\php_db_components_pack\classes\DBItemProperty;
|
||||
use goodboyalex\php_db_components_pack\enums\DBOperation;
|
||||
use goodboyalex\php_db_components_pack\interfaces\IDBItem;
|
||||
use PDO;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use ReflectionProperty;
|
||||
|
||||
/**
|
||||
* Трейт для функций поддержки для работы с базой данных.
|
||||
@@ -44,73 +45,45 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает публичные свойства класса и их значения.
|
||||
* Разбирает объект на свойства.
|
||||
*
|
||||
* @param object $obj Класс.
|
||||
* @param IDBItem $source Объект со свойствами.
|
||||
* @param DBOperation $operation Текущая операция.
|
||||
*
|
||||
* @return array Массив публичных свойств и их значений.
|
||||
* @return ObjectArray Массив свойств и их значений класса, который реализует интерфейс IDBItem.
|
||||
*/
|
||||
private static function GetPublicProperties (object $obj): array
|
||||
private static function GetProperties (IDBItem $source, DBOperation $operation): ObjectArray
|
||||
{
|
||||
// Создаю массив свойств
|
||||
$result = [];
|
||||
$result = new ObjectArray();
|
||||
|
||||
// Получаю массив свойств
|
||||
$properties = get_class_vars(get_class($obj));
|
||||
$properties = get_class_vars(get_class($source));
|
||||
|
||||
// Для каждого свойства
|
||||
foreach ($properties as $key => $value) {
|
||||
// - пропускаю не свойства
|
||||
if (!property_exists($obj, $key))
|
||||
if (!property_exists($source, $key))
|
||||
// -- пропускаю
|
||||
continue;
|
||||
|
||||
// - получаю рефлексию
|
||||
$rProperty = new ReflectionProperty($obj, $key);
|
||||
|
||||
// - пропускаю не публичные свойства
|
||||
if (!$rProperty->isPublic())
|
||||
// -- пропускаю
|
||||
continue;
|
||||
|
||||
// - добавляю в массив свойство и его значение
|
||||
$result[$key] = $value;
|
||||
}
|
||||
|
||||
// Возвращаю результат
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает первичные ключи класса.
|
||||
*
|
||||
* @param IDBItem $source Класс.
|
||||
* @param DBOperation $operation Текущая операция.
|
||||
*
|
||||
* @return array Массив первичных ключей и их значений.
|
||||
*/
|
||||
private function FindPrimaryKeys (IDBItem $source, DBOperation $operation): array
|
||||
{
|
||||
// Создаю массив первичных ключей
|
||||
$pKeys = [];
|
||||
|
||||
// Получаю массив свойств
|
||||
$properties = self::GetPublicProperties($source);
|
||||
|
||||
// Для каждого свойства
|
||||
foreach ($properties as $key => $value) {
|
||||
// - получаю рефлексию
|
||||
// - для класса
|
||||
// - получаю рефлексию класса
|
||||
$reflectedClass = new ReflectionClass(get_class($source));
|
||||
|
||||
try {
|
||||
// - для свойства
|
||||
// - получаю рефлексию свойства
|
||||
$reflectionProperty = $reflectedClass->getProperty($key);
|
||||
}
|
||||
catch (ReflectionException) {
|
||||
// - если ошибка, то вывожу пустой массив
|
||||
return [];
|
||||
return $result;
|
||||
}
|
||||
|
||||
// - пропускаю не публичные свойства
|
||||
if (!$reflectionProperty->isPublic())
|
||||
// -- пропускаю
|
||||
continue;
|
||||
|
||||
// - получаю атрибуты
|
||||
$attributes = $reflectionProperty->getAttributes();
|
||||
|
||||
@@ -121,10 +94,8 @@
|
||||
*/
|
||||
$pkAttr = self::FindAttribute($attributes, PrimaryKey::class);
|
||||
|
||||
// - если на свойстве нет атрибута первичного ключа
|
||||
if ($pkAttr === null)
|
||||
// -- то пропускаю
|
||||
continue;
|
||||
// - это первичный ключ?
|
||||
$isPrimary = $pkAttr !== null;
|
||||
|
||||
/**
|
||||
* Фильтруем поля, игнорируемые для данной операции
|
||||
@@ -134,22 +105,42 @@
|
||||
$ignoreAttr = self::FindAttribute($attributes, IgnoredInDB::class);
|
||||
|
||||
// - если поле игнорируется
|
||||
if ($ignoreAttr !== null) {
|
||||
// -- то проверяю, игнорируется ли данное поле
|
||||
$isIgnore = $ignoreAttr->IgnoredOperations->IsExist(fn (DBOperation $oper) => $oper == $operation);
|
||||
|
||||
// -- если игнорируется
|
||||
if ($isIgnore)
|
||||
// --- то пропускаю
|
||||
continue;
|
||||
}
|
||||
$isIgnore = $ignoreAttr !== null
|
||||
&& $ignoreAttr->IgnoredOperations->IsExist(fn (DBOperation $oper)
|
||||
=> $oper == $operation);
|
||||
|
||||
// - добавляю первичный ключ и его значение
|
||||
$pKeys[$key] = $value;
|
||||
/**
|
||||
* Получаю значение имени поля
|
||||
*
|
||||
* @var FieldName|null $fieldNameAttr Атрибут имени поля.
|
||||
*/
|
||||
$fieldNameAttr = self::FindAttribute($attributes, FieldName::class);
|
||||
|
||||
// Если есть атрибут имени поля, то беру его имя, иначе беру имя свойства
|
||||
$fieldName = $fieldNameAttr !== null ? $fieldNameAttr->FieldName : "";
|
||||
|
||||
/**
|
||||
* Преобразование типа.
|
||||
*
|
||||
* @var ConvertToDB|null $convertAttr Атрибут конвертации.
|
||||
*/
|
||||
$convertAttr = self::FindAttribute($attributes, ConvertToDB::class);
|
||||
|
||||
// - получаю функцию конвертации и сравнения
|
||||
$converterToDB = $convertAttr?->ConvertToDB;
|
||||
$converterFromDB = $convertAttr?->ConvertFromDB;
|
||||
$compareFunc = $convertAttr?->Compare;
|
||||
|
||||
// - создаю объект свойства
|
||||
$item = new DBItemProperty($key, $value, $fieldName, $isPrimary, $isIgnore, $converterToDB,
|
||||
$converterFromDB, $compareFunc);
|
||||
|
||||
// - добавляю в массив
|
||||
$result[] = $item;
|
||||
}
|
||||
|
||||
// Возвращаю найденные ключи
|
||||
return $pKeys;
|
||||
// Возвращаю результат
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,70 +156,25 @@
|
||||
$result = [];
|
||||
|
||||
// Получаю массив свойств
|
||||
$properties = self::GetPublicProperties($source);
|
||||
$properties = self::GetProperties($source, $operation);
|
||||
|
||||
// Для каждого свойства
|
||||
foreach ($properties as $key => $value) {
|
||||
// Получаю рефлексию
|
||||
// - для класса
|
||||
$reflectedClass = new ReflectionClass(get_class($source));
|
||||
try {
|
||||
// - для свойства
|
||||
$reflectionProperty = $reflectedClass->getProperty($key);
|
||||
}
|
||||
catch (ReflectionException $e) {
|
||||
// - если ошибка, то вывожу и выходим
|
||||
$this->HandleException($e);
|
||||
}
|
||||
/**
|
||||
* Для каждого свойства...
|
||||
*
|
||||
* @var DBItemProperty $property Свойство.
|
||||
*/
|
||||
foreach ($properties as $property) {
|
||||
// - пропускаю игнорируемые поля
|
||||
if ($property->IsIgnored)
|
||||
continue;
|
||||
|
||||
// - получаю атрибуты
|
||||
$attributes = $reflectionProperty->getAttributes();
|
||||
// - получаю значение имени поля
|
||||
$fieldName = $property->FieldName;
|
||||
|
||||
/**
|
||||
* Фильтруем поля, игнорируемые для данной операции
|
||||
*
|
||||
* @var IgnoredInDB|null $ignoreAttr Атрибут игнорирования.
|
||||
*/
|
||||
$ignoreAttr = self::FindAttribute($attributes, IgnoredInDB::class);
|
||||
// - преобразую тип
|
||||
$value = call_user_func($property->ConvertToDB, $property->Value);
|
||||
|
||||
// - если поле игнорируется
|
||||
if ($ignoreAttr !== null) {
|
||||
// -- то проверяю, игнорируется ли данное поле
|
||||
$isIgnore = $ignoreAttr->IgnoredOperations->IsExist(fn (DBOperation $oper) => $oper == $operation);
|
||||
|
||||
// -- если игнорируется
|
||||
if ($isIgnore)
|
||||
// --- то пропускаю
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получаю значение имени поля
|
||||
*
|
||||
* @var FieldName|null $fieldNameAttr Атрибут имени поля.
|
||||
*/
|
||||
$fieldNameAttr = self::FindAttribute($attributes, FieldName::class);
|
||||
|
||||
// Если есть атрибут имени поля, то беру его имя, иначе беру имя свойства
|
||||
$fieldName = $fieldNameAttr !== null ? $fieldNameAttr->FieldName : $key;
|
||||
|
||||
/**
|
||||
* Преобразование типа.
|
||||
*
|
||||
* @var ConvertToDB|null $convertAttr Атрибут конвертации.
|
||||
*/
|
||||
$convertAttr = self::FindAttribute($attributes, ConvertToDB::class);
|
||||
|
||||
// Если есть атрибут конвертации
|
||||
if ($convertAttr) {
|
||||
// - то получаю значение функции конвертации
|
||||
$converter = $convertAttr->ConvertToDB;
|
||||
|
||||
// - выполняю функцию конвертации
|
||||
$value = call_user_func($converter, $value);
|
||||
}
|
||||
|
||||
// Добавляю в массив
|
||||
// - добавляю в массив
|
||||
$result[$fieldName] = $value;
|
||||
}
|
||||
|
||||
@@ -255,66 +201,27 @@
|
||||
// Создаём объект желаемого класса
|
||||
$class = new $className();
|
||||
|
||||
// Получаем публичные свойства класса
|
||||
try {
|
||||
$properties = new ReflectionClass($class)->getProperties(ReflectionProperty::IS_PUBLIC);
|
||||
}
|
||||
catch (ReflectionException $exception) {
|
||||
// - в случае ошибки, обрабатываем её
|
||||
$this->HandleException($exception, false);
|
||||
|
||||
// - и возвращаем null
|
||||
return null;
|
||||
}
|
||||
// Получаю свойства класса
|
||||
$properties = self::GetProperties($class, $operation);
|
||||
|
||||
// Массив отношений, содержащий имя поля, имя свойства, метод преобразования
|
||||
$propertiesRelationship = [];
|
||||
|
||||
// Для каждого свойства
|
||||
/**
|
||||
* Для каждого свойства...
|
||||
*
|
||||
* @var DBItemProperty $property Свойство.
|
||||
*/
|
||||
foreach ($properties as $property) {
|
||||
// - получаю атрибуты
|
||||
$attributes = $property->getAttributes();
|
||||
// - пропускаю игнорируемые поля
|
||||
if ($property->IsIgnored)
|
||||
continue;
|
||||
|
||||
/**
|
||||
* Фильтруем поля, игнорируемые для данной операции
|
||||
*
|
||||
* @var IgnoredInDB|null $ignoreAttr Атрибут игнорирования.
|
||||
*/
|
||||
$ignoreAttr = self::FindAttribute($attributes, IgnoredInDB::class);
|
||||
|
||||
// - если поле игнорируется
|
||||
if ($ignoreAttr !== null) {
|
||||
// -- то проверяю, игнорируется ли данное поле
|
||||
$isIgnore = $ignoreAttr->IgnoredOperations->IsExist(fn (DBOperation $oper) => $oper == $operation);
|
||||
|
||||
// -- если игнорируется
|
||||
if ($isIgnore)
|
||||
// --- то пропускаю
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получаю значение имени поля
|
||||
*
|
||||
* @var FieldName|null $fieldNameAttr Атрибут имени поля.
|
||||
*/
|
||||
$fieldNameAttr = self::FindAttribute($attributes, FieldName::class);
|
||||
|
||||
// - если есть атрибут имени поля, то беру его имя, иначе беру имя свойства
|
||||
$fieldName = $fieldNameAttr !== null ? $fieldNameAttr->FieldName : $property->getName();
|
||||
|
||||
/**
|
||||
* Преобразование типа.
|
||||
*
|
||||
* @var ConvertToDB|null $convertAttr Атрибут конвертации.
|
||||
*/
|
||||
$convertAttr = self::FindAttribute($attributes, ConvertToDB::class);
|
||||
|
||||
// - если есть атрибут конвертации, то получаю значение функции конвертации, иначе null
|
||||
$converterFunc = ($convertAttr) ? $convertAttr->ConvertFromDB : null;
|
||||
// - получаю имя поля
|
||||
$fieldName = $property->FieldName;
|
||||
|
||||
// - добавляю в массив отношений
|
||||
$propertiesRelationship[$fieldName] = [$property->getName(), $converterFunc];
|
||||
$propertiesRelationship[$fieldName] = [$property->Name, $property->ConverterFromDB];
|
||||
}
|
||||
|
||||
// Проходим элементы массива из БД
|
||||
|
Reference in New Issue
Block a user