From eeea57209e87ce027eb03d6d94c872c59115f3fb Mon Sep 17 00:00:00 2001 From: babaev-an Date: Wed, 6 Aug 2025 18:10:04 +0300 Subject: [PATCH] 20250806 --- help/class_desc/attributes/AutoIncrement.md | 63 +++++++++++++++++++++ help/class_desc/attributes/Check.md | 62 ++++++++++++++++++++ help/class_desc/attributes/Compare.md | 58 +++++++++++++++++++ help/class_desc/attributes/ConvertToDB.md | 63 +++++++++++++++++++++ help/class_desc/attributes/DataType.md | 59 +++++++++++++++++++ help/class_desc/attributes/DefaultValue.php | 37 ++++++++++++ help/class_desc/attributes/FieldName.php | 37 ++++++++++++ help/class_desc/attributes/ForeignKey.php | 44 ++++++++++++++ help/class_desc/attributes/IgnoredInDB.php | 47 +++++++++++++++ help/class_desc/attributes/NotNull.php | 30 ++++++++++ help/class_desc/attributes/PrimaryKey.php | 29 ++++++++++ help/class_desc/attributes/Unique.php | 30 ++++++++++ help/class_desc/enums/DBDriver.md | 2 +- help/class_desc/enums/DBOperation.md | 2 +- help/class_desc/enums/DBType.md | 2 +- sources/attributes/Compare.php | 38 +++++++++++++ sources/attributes/ConvertToDB.php | 9 +-- sources/classes/Condition.php | 27 +++++++-- sources/traits/Database/DatabaseSpecial.php | 13 ++++- 19 files changed, 636 insertions(+), 16 deletions(-) create mode 100644 help/class_desc/attributes/AutoIncrement.md create mode 100644 help/class_desc/attributes/Check.md create mode 100644 help/class_desc/attributes/Compare.md create mode 100644 help/class_desc/attributes/ConvertToDB.md create mode 100644 help/class_desc/attributes/DataType.md create mode 100644 help/class_desc/attributes/DefaultValue.php create mode 100644 help/class_desc/attributes/FieldName.php create mode 100644 help/class_desc/attributes/ForeignKey.php create mode 100644 help/class_desc/attributes/IgnoredInDB.php create mode 100644 help/class_desc/attributes/NotNull.php create mode 100644 help/class_desc/attributes/PrimaryKey.php create mode 100644 help/class_desc/attributes/Unique.php create mode 100644 sources/attributes/Compare.php diff --git a/help/class_desc/attributes/AutoIncrement.md b/help/class_desc/attributes/AutoIncrement.md new file mode 100644 index 0000000..d099cca --- /dev/null +++ b/help/class_desc/attributes/AutoIncrement.md @@ -0,0 +1,63 @@ +# Атрибут `AutoIncrement` + +Атрибут `AutoIncrement` используется для пометки полей в моделях данных, которые будут автоматически заполняться +уникальным значением при каждом новом сохранении записи. Обычно он применяется для идентификации уникальных записей, +таких как первичные ключи. + +## Основное назначение + +Этот атрибут необходим для того, чтобы отметить поля, значения которых не задаются вручную, а генерируются автоматически +самой базой данных при вставке нового элемента. Например, если поле объявлено как автоинкрементируемое (AUTO_INCREMENT в +MySQL, SERIAL в PostgreSQL), то именно этот атрибут поможет разработчику ясно выразить намерение, что такое поле само +получает уникальный идентификатор. + +## Пример использования атрибута + +Предположим, у вас есть простая модель данных, описывающая пользователей, где каждое поле соответствует столбцу в базе +данных: + +```php +use goodboyalex\php_db_components_pack\attributes\AutoIncrement; + +final class User +{ + #[AutoIncrement] + private int $Id; + + private string $Name; + + private string $Email; + + // ... +} +``` + +Здесь атрибут `#[AutoIncrement]` указывает, что поле `$Id` будет автоматически получать уникальные значения при создании +новых записей. + +## Пространство имён + +Атрибут объявлен в пространстве имён: + +```php +namespace goodboyalex\php_db_components_pack\attributes; +``` + +### Версии и автор + +- **Автор**: Александр Бабаев +- **Версия**: 1.0 +- **Дата выпуска**: с версии 1.0 + +### Особенности + +- **Только для свойств (fields)** + Атрибут применим исключительно к свойствам классов, которые представляют собой поля базы данных. + +### Когда использовать атрибут? + +Атрибут `AutoIncrement` рекомендуется использовать в случаях, когда важно подчеркнуть автоматическое поведение поля при +вставке новых записей в базу данных. Особенно это актуально для идентификационных полей, таких как первичные ключи, где +обеспечение уникальности критично для целостности данных. + +[На главную](../../index.md) \ No newline at end of file diff --git a/help/class_desc/attributes/Check.md b/help/class_desc/attributes/Check.md new file mode 100644 index 0000000..a5e868b --- /dev/null +++ b/help/class_desc/attributes/Check.md @@ -0,0 +1,62 @@ +# Атрибут `Check` + +Атрибут `Check` предназначен для установки ограничений на добавляемые данные путём наложения проверок при внесении новой +записи в базу данных. Это даёт возможность заранее определить, какое условие должно соблюдаться для того, чтобы новая +запись была сохранена. + +## Основное назначение + +Атрибут позволяет задать дополнительное правило (условие), которое будет проверяться всякий раз, когда создаётся новая +запись в базе данных. Таким образом, можно гарантировать соблюдение бизнес-правил и повысить целостность данных. + +## Пример использования атрибута + +Предположим, у вас есть модель данных, описывающая пользователей, и вы хотите убедиться, что каждое новое имя +пользователя начинается с заглавной буквы: + +```php +use goodboyalex\php_db_components_pack\attributes\Check; +use goodboyalex\php_db_components_pack\attributes\FieldName; +use goodboyalex\php_db_components_pack\classes\ConditionBuilder; + +final class User +{ + #[Check(new ConditionBuilder()->WhereEqual('FUNC:SUBSTR(name, 1, 1)', 'FUNC:UPPER(SUBSTR(name, 1, 1)) + ')), FieldName('name')] + private string $Name; + + private string $email; + + //... +} +``` + +В данном примере атрибут `#[Check]` применяется к полю `name`, и любое новое значение поля проходит проверку на то, +что первая буква должна быть заглавной. + +## Пространство имён + +Атрибут объявлен в пространстве имён: + +```php +namespace goodboyalex\php_db_components_pack\attributes; +``` + +## Версии и автор + +- **Автор**: Александр Бабаев +- **Версия**: 1.0 +- **Дата выпуска**: с версии 1.0 + +## Особенности + +- **Применяется только к полям (properties)** Атрибут используется исключительно для аннотирования полей классов, + которые соответствуют столбцам базы данных. + +## Когда использовать атрибут? + +Атрибут `Check` подходит для ситуаций, когда нужно обеспечить дополнительную защиту данных и ограничить ввод +некорректных значений. Например, вы можете потребовать, чтобы пароль состоял минимум из восьми символов, или +удостовериться, что введённый адрес электронной почты действительно валиден. + +[На главную](../../index.md) \ No newline at end of file diff --git a/help/class_desc/attributes/Compare.md b/help/class_desc/attributes/Compare.md new file mode 100644 index 0000000..fd00cd0 --- /dev/null +++ b/help/class_desc/attributes/Compare.md @@ -0,0 +1,58 @@ +# Атрибут `Compare` + +Атрибут `Compare` предназначен для задания специальных процедур сравнения значений поля при работе с базой данных. Он +позволяет реализовать кастомные механизмы сравнения, отличающиеся от стандартного равенства, что бывает крайне полезно +при сложной логике работы с данными. + +## Основное назначение + +Атрибут позволяет указать собственный метод сравнения значений, применяемый к определенному полю в базе данных. +Например, это может понадобиться, если простое сравнение двух значений недостаточно точно отражает вашу бизнес-логику ( +например, если нужно сравнивать значения с учётом округления или игнорируя регистр букв). + +## Пример использования атрибута + +Допустим, у вас есть модель данных, включающая поле, содержащее имя пользователя, и вы хотите сравнить имена независимо +от регистра: + +```php +use goodboyalex\php_db_components_pack\attributes\Compare; + +final class User +{ + #[Compare(fn($left, $right) => strcasecmp($left, $right))] + private string $Name; + + // Остальные поля и геттеры/сеттеры... +} +``` + +В данном примере атрибут `#[Compare]` применяется к полю `$Name`, и указанное замыкание (closure) реализует +сравнение строк без учёта регистра. + +## Пространство имён + +Атрибут объявлен в пространстве имён: + +```php +namespace goodboyalex\php_db_components_pack\attributes; +``` + +### Версии и автор + +- **Автор**: Александр Бабаев +- **Версия**: 1.0 +- **Дата выпуска**: с версии 1.0 + +## Особенности + +- **Применяется только к полям (properties)** + Атрибут используется исключительно для аннотирования полей классов, которые соответствуют столбцам базы данных. + +## Когда использовать атрибут? + +Атрибут `Compare` идеально подойдёт, когда вам необходимо установить особое правило сравнения значений. Например, если +требуется учесть особенности сортировки, учета регистров или даже допустимые погрешности при сравнении числовых +значений. + +[На главную](../../index.md) \ No newline at end of file diff --git a/help/class_desc/attributes/ConvertToDB.md b/help/class_desc/attributes/ConvertToDB.md new file mode 100644 index 0000000..701fa3d --- /dev/null +++ b/help/class_desc/attributes/ConvertToDB.md @@ -0,0 +1,63 @@ +# Атрибут `ConvertToDB` + +Атрибут `ConvertToDB` предназначен для настройки процесса преобразования значений при взаимодействии с базой данных. Он +позволяет задать специальные методы для преобразования данных между внутренним представлением и формой, подходящей для +сохранения в базе данных. + +## Основное назначение + +Атрибут позволяет настроить индивидуальные процедуры для преобразования данных, поступающих из базы данных и обратно. +Часто бывает необходимо изменять формат данных при передаче их между слоями приложения и хранилищем, например, +преобразовать JSON в объект или нормализовать строку для хранения в определенном формате. + +## Пример использования атрибута + +Допустим, у вас есть модель данных, содержащая поле, которое хранит метаданные в формате JSON, и вы хотите, чтобы это +поле было сериализовано в JSON при сохранении в базу данных и десериализовано обратно при извлечении: + +```php +use goodboyalex\php_db_components_pack\attributes\ConvertToDB; +use goodboyalex\php_db_components_pack\attributes\DataType; +use goodboyalex\php_db_components_pack\enums\DBType; + +final class Product +{ + #[ConvertToDB( + fromType: fn($val) => json_decode($val, true), + toType: fn($val) => json_encode($val) + ), DataType(DBType::STRING)] + public array $MetaData; + + // Другие поля и геттеры/сеттеры... +} +``` + +В данном примере атрибут `#[ConvertToDB]` применяется к полю `$MetaData`, и два заданных замыкания определяют порядок +преобразования данных при чтении и записи. + +## Пространство имён + +Атрибут объявлен в пространстве имён: + +```php +namespace goodboyalex\php_db_components_pack\attributes; +``` + +## Версии и автор + +- **Автор**: Александр Бабаев +- **Версия**: 1.0 +- **Дата выпуска**: с версии 1.0 + +## Особенности + +- **Применяется только к полям (properties)** + Атрибут используется исключительно для аннотирования полей классов, которые соответствуют столбцам базы данных. + +## Когда использовать атрибут? + +Атрибут `ConvertToDB` пригодится, когда возникает необходимость нестандартного преобразования данных. Например, если вы +работаете с JSON-данными, XML-документами или бинарными изображениями, и нужно аккуратно сохранять и извлекать эти +данные из базы данных. + +[На главную](../../index.md) \ No newline at end of file diff --git a/help/class_desc/attributes/DataType.md b/help/class_desc/attributes/DataType.md new file mode 100644 index 0000000..3d0bac1 --- /dev/null +++ b/help/class_desc/attributes/DataType.md @@ -0,0 +1,59 @@ +# Атрибут `DataType` + +Атрибут `DataType` предназначен для указания типа данных и размера поля, используемого в базе данных. Он позволяет чётко +определять, какой тип данных хранится в конкретном поле и каким образом он представлен в базе данных. + +## Основное назначение + +Атрибут используется для явного указания типа данных, хранимых в соответствующем поле модели данных. Это важно, потому +что разные базы данных поддерживают различные типы данных, и важно обеспечить точное соответствие между моделью данных и +физической схемой базы данных. + +## Пример использования атрибута + +Допустим, у вас есть модель данных, описывающая товары, и вы хотите указать, что цена товара представлена числом с +плавающей точкой, а название товара ограничено длиной в 100 символов: + +```php +use goodboyalex\php_db_components_pack\attributes\DataType; +use goodboyalex\php_db_components_pack\enums\DBType; + +final class Product +{ + #[DataType(DBType::FLOAT)] + private float $Price; + + #[DataType(DBType::STRING, size: 100)] + private string $Title; + + // Остальные поля и геттеры/сеттеры... +} +``` + +В данном примере атрибут `#[DataType]` применяется к двум полям: одному для цены и другому для заголовка продукта. + +## Пространство имён + +Атрибут объявлен в пространстве имён: + +```php +namespace goodboyalex\php_db_components_pack\attributes; +``` + +## Версия и автор + +- **Автор**: Александр Бабаев +- **Версия**: 1.0 +- **Дата выпуска**: с версии 1.0 + +## Особенности + +- **Применяется только к полям (properties)** + Атрибут используется исключительно для аннотирования полей классов, которые соответствуют столбцам базы данных. + +## Когда использовать атрибут? + +Атрибут `DataType` идеален, когда вам нужно явно указать тип данных, который сохраняется в поле базы данных. Это может +быть особенно полезно при миграции данных или проверке соответствия схемы базы данных вашим моделям. + +[На главную](../../index.md) \ No newline at end of file diff --git a/help/class_desc/attributes/DefaultValue.php b/help/class_desc/attributes/DefaultValue.php new file mode 100644 index 0000000..37cda52 --- /dev/null +++ b/help/class_desc/attributes/DefaultValue.php @@ -0,0 +1,37 @@ +Value = $value; + } + } \ No newline at end of file diff --git a/help/class_desc/attributes/FieldName.php b/help/class_desc/attributes/FieldName.php new file mode 100644 index 0000000..96fe632 --- /dev/null +++ b/help/class_desc/attributes/FieldName.php @@ -0,0 +1,37 @@ +FieldName = $fieldName; + } + } \ No newline at end of file diff --git a/help/class_desc/attributes/ForeignKey.php b/help/class_desc/attributes/ForeignKey.php new file mode 100644 index 0000000..df29b7b --- /dev/null +++ b/help/class_desc/attributes/ForeignKey.php @@ -0,0 +1,44 @@ +TableName = $table; + $this->FieldName = $fieldName; + } + } \ No newline at end of file diff --git a/help/class_desc/attributes/IgnoredInDB.php b/help/class_desc/attributes/IgnoredInDB.php new file mode 100644 index 0000000..d1d6878 --- /dev/null +++ b/help/class_desc/attributes/IgnoredInDB.php @@ -0,0 +1,47 @@ +IgnoredOperations = new ObjectArray($ignoredOperations); + } + } \ No newline at end of file diff --git a/help/class_desc/attributes/NotNull.php b/help/class_desc/attributes/NotNull.php new file mode 100644 index 0000000..ff32b90 --- /dev/null +++ b/help/class_desc/attributes/NotNull.php @@ -0,0 +1,30 @@ +Function = $function; + } + } \ No newline at end of file diff --git a/sources/attributes/ConvertToDB.php b/sources/attributes/ConvertToDB.php index 34f23da..8ce37e4 100644 --- a/sources/attributes/ConvertToDB.php +++ b/sources/attributes/ConvertToDB.php @@ -31,22 +31,15 @@ */ public ?Closure $ConvertFromDB; - /** - * @var Closure|null Метод сравнения типов. - */ - public ?Closure $Compare; - /** * Конструктор. * * @param callable|null $fromType Метод конвертации из типа для заполнения таблицы базы данных. * @param callable|null $toType Метод конвертации в тип для заполнения таблицы базы данных. - * @param callable|null $compare Метод сравнения типов. */ - public function __construct (?callable $fromType = null, ?callable $toType = null, ?callable $compare = null) + public function __construct (?callable $fromType = null, ?callable $toType = null) { $this->ConvertToDB = $fromType; $this->ConvertFromDB = $toType; - $this->Compare = $compare; } } \ No newline at end of file diff --git a/sources/classes/Condition.php b/sources/classes/Condition.php index 03f0dfc..d6cbb3b 100644 --- a/sources/classes/Condition.php +++ b/sources/classes/Condition.php @@ -3,6 +3,7 @@ namespace goodboyalex\php_db_components_pack\classes; use goodboyalex\php_components_pack\classes\Tuple; + use goodboyalex\php_components_pack\extensions\StringExtension; use goodboyalex\php_components_pack\interfaces\IArrayable; use PHPUnit\Event\InvalidArgumentException; @@ -106,11 +107,29 @@ */ public function Get (int $index = 0): Tuple { - // Формирование условия SQL - $sql = "`$this->ColumnName` $this->Operator :prop_$index"; + // Начинаю формировать SQL + $sql = (!str_starts_with($this->ColumnName, "FUNC:")) + ? "`$this->ColumnName`" + : StringExtension::Replace('FUNC:', '', $this->ColumnName); - // Формирование параметров запроса - $params = [":prop_$index" => $this->Value]; + // Добавляю оператор + $sql .= " $this->Operator "; + + // Если это строковое значение и передаётся функция + if (is_string($this->Value) && str_starts_with($this->Value, "FUNC:")) { + // - то добавляю код SQL этой функции + $sql .= StringExtension::Replace('FUNC:', '', $this->ColumnName); + + // - и устанавливаю пустые параметры запроса + $params = []; + } + else { + // - в противном случае, добавляю "муляжное" значение + $sql .= ":prop_$index"; + + // - а настоящее пропишем в параметрах запроса + $params = [":prop_$index" => $this->Value]; + } // Возвращение результата return new Tuple($sql, $params); diff --git a/sources/traits/Database/DatabaseSpecial.php b/sources/traits/Database/DatabaseSpecial.php index e3bd42e..989f76e 100644 --- a/sources/traits/Database/DatabaseSpecial.php +++ b/sources/traits/Database/DatabaseSpecial.php @@ -2,6 +2,7 @@ /** * @noinspection SqlNoDataSourceInspection + * @noinspection PhpMultipleClassDeclarationsInspection */ namespace goodboyalex\php_db_components_pack\traits\Database; @@ -11,6 +12,7 @@ use goodboyalex\php_components_pack\classes\Tuple; use goodboyalex\php_db_components_pack\attributes\AutoIncrement; use goodboyalex\php_db_components_pack\attributes\Check; + use goodboyalex\php_db_components_pack\attributes\Compare; use goodboyalex\php_db_components_pack\attributes\ConvertToDB; use goodboyalex\php_db_components_pack\attributes\DataType; use goodboyalex\php_db_components_pack\attributes\DefaultValue; @@ -129,7 +131,16 @@ // - получаю функцию конвертации и сравнения $converterToDB = $convertAttr?->ConvertToDB; $converterFromDB = $convertAttr?->ConvertFromDB; - $compareFunc = $convertAttr?->Compare; + + /** + * Сравнение значений. + * + * @var Compare|null $compareAttr Атрибут сравнения значений. + */ + $compareAttr = self::FindAttribute($attributes, Compare::class); + + // - получаю функцию сравнения + $compareFunc = $compareAttr?->Function; // - получаем свойства столбца /**