diff --git a/help/class_desc/attributes/Compare.md b/help/class_desc/attributes/Compare.md index fd00cd0..58e4273 100644 --- a/help/class_desc/attributes/Compare.md +++ b/help/class_desc/attributes/Compare.md @@ -10,25 +10,48 @@ Например, это может понадобиться, если простое сравнение двух значений недостаточно точно отражает вашу бизнес-логику ( например, если нужно сравнивать значения с учётом округления или игнорируя регистр букв). +## Синтаксис использования + +Атрибут принимает один обязательный параметр типа `string|array|null`, который определяет способ сравнения. Возможны +следующие варианты: + +* Строка — имя статического метода. +* Массив — [класс, метод]. +* null — сравнение по умолчанию. + ## Пример использования атрибута -Допустим, у вас есть модель данных, включающая поле, содержащее имя пользователя, и вы хотите сравнить имена независимо -от регистра: +### Пример 1: Использование статического метода ```php use goodboyalex\php_db_components_pack\attributes\Compare; final class User { - #[Compare(fn($left, $right) => strcasecmp($left, $right))] - private string $Name; - - // Остальные поля и геттеры/сеттеры... + #[Compare('App\Comparators\StringComparator::caseInsensitiveCompare')] + public string $Name; } ``` -В данном примере атрибут `#[Compare]` применяется к полю `$Name`, и указанное замыкание (closure) реализует -сравнение строк без учёта регистра. +#### Пример 2: Использование массива для вызова метода + +```php +final class Measurement +{ + #[Compare('App\Comparators\NumberComparator', 'compareWithTolerance')] + public float $Value; +} +``` + +#### Пример 3: Сравнение по умолчанию + +```php +final class Event +{ + #[Compare(null)] + public string $Date; +} +``` ## Пространство имён @@ -49,6 +72,13 @@ namespace goodboyalex\php_db_components_pack\attributes; - **Применяется только к полям (properties)** Атрибут используется исключительно для аннотирования полей классов, которые соответствуют столбцам базы данных. +## Важные замечания + +* Все указанные методы должны быть статическими. +* При некорректном определении компаратора будет выброшено исключение. +* Рекомендуется создавать отдельные классы компараторов для лучшей поддерживаемости кода. +* Методы сравнения должны корректно обрабатывать все возможные значения поля. + ## Когда использовать атрибут? Атрибут `Compare` идеально подойдёт, когда вам необходимо установить особое правило сравнения значений. Например, если diff --git a/help/class_desc/attributes/ConvertToDB.md b/help/class_desc/attributes/ConvertToDB.md index 701fa3d..2928cb4 100644 --- a/help/class_desc/attributes/ConvertToDB.md +++ b/help/class_desc/attributes/ConvertToDB.md @@ -10,10 +10,16 @@ Часто бывает необходимо изменять формат данных при передаче их между слоями приложения и хранилищем, например, преобразовать JSON в объект или нормализовать строку для хранения в определенном формате. -## Пример использования атрибута +## Синтаксис использования -Допустим, у вас есть модель данных, содержащая поле, которое хранит метаданные в формате JSON, и вы хотите, чтобы это -поле было сериализовано в JSON при сохранении в базу данных и десериализовано обратно при извлечении: +Атрибут принимает два параметра: + +* **fromType** - определение конвертации из БД (может быть строкой, массивом или `null`). По умолчанию, `null`. +* **toType** - определение конвертации в БД (может быть строкой, массивом или `null`). По умолчанию, `null`. + +### Примеры использования + +#### Пример 1: Использование строковых вызовов ```php use goodboyalex\php_db_components_pack\attributes\ConvertToDB; @@ -23,17 +29,34 @@ 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)] + 'App\Converters\JsonConverter::decode', + 'App\Converters\JsonConverter::encode' + )] public array $MetaData; - - // Другие поля и геттеры/сеттеры... } ``` -В данном примере атрибут `#[ConvertToDB]` применяется к полю `$MetaData`, и два заданных замыкания определяют порядок -преобразования данных при чтении и записи. +#### Пример 2: Использование массивов для вызова методов + +```php +final class Product +{ + #[ConvertToDB( + ['App\Converters\DateConverter', 'convertToInternal'], + ['App\Converters\DateConverter', 'convertToDB'] + )] + public string $created_at; +} +``` + +## Параметры атрибута + +* **fromType** (string|array|null) - определение конвертации из БД + * Строка: имя статического метода + * Массив: [класс, метод] +* **toType** (string|array|null) - определение конвертации в БД + * Строка: имя статического метода + * Массив: [класс, метод] ## Пространство имён @@ -51,8 +74,10 @@ namespace goodboyalex\php_db_components_pack\attributes; ## Особенности -- **Применяется только к полям (properties)** - Атрибут используется исключительно для аннотирования полей классов, которые соответствуют столбцам базы данных. +* Атрибут применяется только к свойствам класса +* Поддерживает два формата определения конвертаций +* Автоматически создаёт замыкания на основе переданных данных +* Позволяет использовать любые статические методы для конвертации ## Когда использовать атрибут? diff --git a/sources/attributes/Compare.php b/sources/attributes/Compare.php index c2b2d17..e3b8c49 100644 --- a/sources/attributes/Compare.php +++ b/sources/attributes/Compare.php @@ -29,10 +29,46 @@ /** * Конструктор. * - * @param callable|null $function Метод сравнения значений. + * @param string|array|null $function Метод сравнения значений (может быть строкой (имя функции), может быть + * массивом (имя класса, имя метода) и null (по умолчанию)). */ - public function __construct (?callable $function = null) + public function __construct (string|array|null $function = null) { - $this->Function = $function; + // Преобразуем входные данные в замыкания + $this->Function = $this->CreateCallback($function); + } + + /** + * Создает замыкание из переданного значения + * + * @param string|array|null $callbackData Данные для создания колбэка + * + * @return Closure|null + */ + private function CreateCallback (string|array|null $callbackData): ?Closure + { + // Если передан null + if ($callbackData === null) + // - возвращаем null + return null; + + // Если передана строка - считаем это именем статического метода + if (is_string($callbackData)) + // - создаём замыкание и возращаем его + return static fn (mixed $value1, mixed $value2): bool + => call_user_func($callbackData, $value1, $value2); + + // Если передан массив [класс, метод] + if (is_array($callbackData)) { + // - разбираем его + [$class, $method] = $callbackData; + + // - создаём замыкание и возращаем его + return static fn (mixed $value1, mixed $value2): bool + => call_user_func([$class, $method], $value1, $value2); + } + + // В случае ошибки возвращаем null + return null; } } \ No newline at end of file diff --git a/sources/attributes/ConvertToDB.php b/sources/attributes/ConvertToDB.php index 8ce37e4..a571b64 100644 --- a/sources/attributes/ConvertToDB.php +++ b/sources/attributes/ConvertToDB.php @@ -34,12 +34,48 @@ /** * Конструктор. * - * @param callable|null $fromType Метод конвертации из типа для заполнения таблицы базы данных. - * @param callable|null $toType Метод конвертации в тип для заполнения таблицы базы данных. + * @param string|array|null $fromType Метод конвертации из типа для заполнения таблицы базы данных (может + * быть строкой (имя функции), может быть массивом (имя класса, имя метода) и null (по умолчанию)). + * @param string|array|null $toType Метод конвертации в тип для заполнения таблицы базы данных (может быть + * строкой (имя функции), может быть массивом (имя класса, имя метода) и null (по умолчанию)). */ - public function __construct (?callable $fromType = null, ?callable $toType = null) + public function __construct (string|array|null $fromType = null, string|array|null $toType = null) { $this->ConvertToDB = $fromType; $this->ConvertFromDB = $toType; } + + /** + * Создает замыкание из переданного значения + * + * @param string|array|null $callbackData Данные для создания колбэка + * + * @return Closure|null + */ + private function CreateCallback (string|array|null $callbackData): ?Closure + { + // Если передан null + if ($callbackData === null) + // - возвращаем null + return null; + + // Если передана строка - считаем это именем статического метода + if (is_string($callbackData)) + // - создаём замыкание и возращаем его + return static fn (mixed $value): mixed + => call_user_func($callbackData, $value); + + // Если передан массив [класс, метод] + if (is_array($callbackData)) { + // - разбираем его + [$class, $method] = $callbackData; + + // - создаём замыкание и возращаем его + return static fn (mixed $value): mixed + => call_user_func([$class, $method], $value); + } + + // В случае ошибки возвращаем null + return null; + } } \ No newline at end of file