From da74e38629bae1235c2e4304cb00cb28ac8b9b10 Mon Sep 17 00:00:00 2001 From: Yurun Date: Sun, 26 May 2024 21:46:41 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E9=87=8D=E6=9E=84=20Model=20Meta=20?= =?UTF-8?q?=E7=9A=84=E6=B3=A8=E8=A7=A3=E7=AE=A1=E7=90=86=20(#701)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/src/Annotation/Column.php | 6 + .../model/src/Annotation/CreateTime.php | 26 ++ .../model/src/Annotation/ListSeparator.php | 22 ++ .../model/src/Annotation/UpdateTime.php | 26 ++ src/Components/model/src/BaseModel.php | 7 +- src/Components/model/src/Meta.php | 238 +++++------------- src/Components/model/src/Model.php | 13 +- src/Components/model/src/RedisModel.php | 12 +- src/Components/model/src/Relation/Query.php | 9 +- .../model/src/Traits/TJsonValue.php | 19 +- .../model/src/Traits/TModelQuery.php | 4 +- .../model/tests/Model/CreateTime.php | 4 +- .../model/tests/Model/UpdateTime.php | 4 +- 13 files changed, 181 insertions(+), 209 deletions(-) create mode 100644 src/Components/model/src/Annotation/CreateTime.php create mode 100644 src/Components/model/src/Annotation/ListSeparator.php create mode 100644 src/Components/model/src/Annotation/UpdateTime.php diff --git a/src/Components/model/src/Annotation/Column.php b/src/Components/model/src/Annotation/Column.php index 78daad1fa9..232ddfbf6b 100644 --- a/src/Components/model/src/Annotation/Column.php +++ b/src/Components/model/src/Annotation/Column.php @@ -58,11 +58,15 @@ public function __construct( /** * save/update 模型时是否将当前时间写入该字段;支持 date/time/datetime/timestamp/year/int/bigint;当字段为 int 类型,写入秒级时间戳;当字段为 bigint 类型,写入毫秒级时间戳. * + * @deprecated 3.1 + * * @var bool|int */ public $updateTime = false, /** * 列表分割字符串;如果字段类型为list,并且此字段不为null,读取时会处理为数组,写入时会处理为字符串. + * + * @deprecated 3.1 */ public ?string $listSeparator = null, /** @@ -80,6 +84,8 @@ public function __construct( /** * save/create 模型时是否将当前时间写入该字段,save时表有自增ID主键才支持;支持 date/time/datetime/timestamp/year/int/bigint;当字段为 int 类型,写入秒级时间戳;当字段为 bigint 类型,写入毫秒级时间戳. * + * @deprecated 3.1 + * * @var bool|int */ public $createTime = false diff --git a/src/Components/model/src/Annotation/CreateTime.php b/src/Components/model/src/Annotation/CreateTime.php new file mode 100644 index 0000000000..59c71e5e69 --- /dev/null +++ b/src/Components/model/src/Annotation/CreateTime.php @@ -0,0 +1,26 @@ +getExtractPropertys(); + /** @var ExtractProperty[][] $extractProperties */ + $extractProperties = $meta->getPropertyAnnotations()[ExtractProperty::class] ?? []; if ( (($name = $key) && isset($extractProperties[$name])) || (($name = Text::toUnderScoreCase($key)) && isset($extractProperties[$name])) @@ -387,7 +390,7 @@ public function toArray(): array if (null === $value) { // JsonNotNull 注解支持 - if (isset(($propertyJsonNotNullMap ??= ($meta ??= $this->__meta)->getPropertyJsonNotNullMap())[$name])) + if (isset(($meta ??= $this->__meta)->getPropertyAnnotations()[JsonNotNull::class][$name])) { continue; } diff --git a/src/Components/model/src/Meta.php b/src/Components/model/src/Meta.php index 7a173e5e54..2df4df72bb 100644 --- a/src/Components/model/src/Meta.php +++ b/src/Components/model/src/Meta.php @@ -5,17 +5,13 @@ namespace Imi\Model; use Imi\Bean\Annotation\AnnotationManager; +use Imi\Bean\Annotation\Base; use Imi\Config; use Imi\Model\Annotation\Column; use Imi\Model\Annotation\Entity; -use Imi\Model\Annotation\ExtractProperty; use Imi\Model\Annotation\Id; -use Imi\Model\Annotation\JsonDecode; -use Imi\Model\Annotation\JsonEncode; -use Imi\Model\Annotation\JsonNotNull; use Imi\Model\Annotation\Serializable; use Imi\Model\Annotation\Serializables; -use Imi\Model\Annotation\Sql; use Imi\Model\Annotation\Table; use Imi\Util\Text; @@ -95,25 +91,6 @@ class Meta */ private bool $camel = true; - /** - * 序列化注解. - */ - private ?Serializables $serializables = null; - - /** - * 序列化注解列表. - * - * @var \Imi\Model\Annotation\Serializable[][] - */ - private array $serializableSets = []; - - /** - * 提取属性注解. - * - * @var \Imi\Model\Annotation\ExtractProperty[][] - */ - private array $extractPropertys = []; - /** * 是否有关联. */ @@ -124,44 +101,6 @@ class Meta */ private ?string $autoIncrementField = null; - /** - * JsonNotNull 注解集合. - * - * @var \Imi\Model\Annotation\JsonNotNull[][] - */ - private array $propertyJsonNotNullMap = []; - - /** - * JSON 序列化时的配置. - */ - private ?JsonEncode $jsonEncode = null; - - /** - * 针对字段设置的 JSON 序列化时的配置. - * - * @var JsonEncode[] - */ - private array $fieldsJsonEncode = []; - - /** - * JSON 反序列化时的配置. - */ - private ?JsonDecode $jsonDecode = null; - - /** - * 针对字段设置的 JSON 反序列化时的配置. - * - * @var JsonDecode[] - */ - private array $fieldsJsonDecode = []; - - /** - * 定义 SQL 语句的字段列表. - * - * @var \Imi\Model\Annotation\Sql[][] - */ - private array $sqlColumns = []; - /** * 真实的模型类名. */ @@ -184,6 +123,20 @@ class Meta */ private bool $incrUpdate = false; + /** + * 类注解集合. + * + * @var \Imi\Bean\Annotation\Base[][] + */ + private array $classAnnotations = []; + + /** + * 属性注解集合. + * + * @var \Imi\Bean\Annotation\Base[][][] + */ + private array $propertyAnnotations = []; + public function __construct(string $modelClass, /** * 是否为继承父类的模型. @@ -201,33 +154,27 @@ public function __construct(string $modelClass, $modelConfig = Config::get('@app.models.' . $realModelClass); $this->realModelClass = $realModelClass; $this->className = $modelClass; - $annotations = AnnotationManager::getClassAnnotations($realModelClass, [ - Table::class, - Entity::class, - JsonEncode::class, - JsonDecode::class, - Serializables::class, - ], true, true); - $propertyAnnotations = AnnotationManager::getPropertiesAnnotations($realModelClass, [ - Column::class, - Serializable::class, - ExtractProperty::class, - JsonNotNull::class, - Sql::class, - JsonEncode::class, - JsonDecode::class, - Id::class, - ]); - /** @var \Imi\Model\Annotation\Table|null $table */ - $table = $annotations[Table::class]; - /** @var \Imi\Model\Annotation\Entity|null $entity */ - $entity = $annotations[Entity::class]; - $this->jsonEncode = $annotations[JsonEncode::class]; - $this->jsonDecode = $annotations[JsonDecode::class]; - /** @var Serializables|null $serializables */ - $serializables = $this->serializables = $annotations[Serializables::class]; - if ($table) + // 类注解 + $classAnnotations = []; + /** @var Base $annotation */ + foreach (AnnotationManager::getClassAnnotations($realModelClass) as $annotation) + { + $classAnnotations[$annotation::class][] = $annotation; + } + $this->classAnnotations = $classAnnotations; + // 属性注解 + $propertyAnnotations = []; + foreach (AnnotationManager::getPropertiesAnnotations($realModelClass) as $propertyName => $annotations) + { + foreach ($annotations as $annotation) + { + $propertyAnnotations[$annotation::class][$propertyName][] = $annotation; + } + } + $this->propertyAnnotations = $propertyAnnotations; + if ($table = $classAnnotations[Table::class][0] ?? null) { + /** @var \Imi\Model\Annotation\Table|null $table */ $this->dbPoolName = $modelConfig['poolName'] ?? $table->dbPoolName; $this->id = $id = (array) $table->id; $this->setTableName($modelConfig['name'] ?? $table->name); @@ -237,7 +184,7 @@ public function __construct(string $modelClass, { $id = []; } - if ($ids = $propertyAnnotations[Id::class]) + if ($ids = ($propertyAnnotations[Id::class] ?? null)) { $setToId = !$id; /** @var Id[] $propertyIds */ @@ -266,7 +213,7 @@ public function __construct(string $modelClass, $this->firstId = $id[0] ?? null; /** @var Column[] $fields */ $fields = $dbFields = []; - foreach ($propertyAnnotations[Column::class] as $name => $columns) + foreach ($propertyAnnotations[Column::class] ?? [] as $name => $columns) { /** @var Column $column */ $column = $columns[0]; @@ -283,13 +230,6 @@ public function __construct(string $modelClass, $this->autoIncrementField = $name; } } - /** @var Serializable[][] $serializableSets */ - $serializableSets = $this->serializableSets = $propertyAnnotations[Serializable::class]; - $this->extractPropertys = $propertyAnnotations[ExtractProperty::class]; - $this->propertyJsonNotNullMap = $propertyAnnotations[JsonNotNull::class]; - $this->sqlColumns = $propertyAnnotations[Sql::class]; - $this->fieldsJsonEncode = $propertyAnnotations[JsonEncode::class]; - $this->fieldsJsonDecode = $propertyAnnotations[JsonDecode::class]; $this->relation = $relation = ModelRelationManager::hasRelation($realModelClass); if ($relation) { @@ -303,10 +243,13 @@ public function __construct(string $modelClass, } $this->dbFields = $dbFields; $this->fields = $fields; + /** @var \Imi\Model\Annotation\Entity|null $entity */ + $entity = $classAnnotations[Entity::class][0] ?? null; $this->camel = $camel = $entity->camel ?? true; $this->bean = $entity->bean ?? true; $this->incrUpdate = $entity->incrUpdate ?? false; $serializableFieldNames = $parsedSerializableFieldNames = $fieldNames = []; + $serializableSets = $propertyAnnotations[Serializable::class] ?? []; foreach ($fields as $fieldName => $column) { $fieldNames[] = $fieldName; @@ -332,8 +275,9 @@ public function __construct(string $modelClass, continue; } } - elseif ($serializables) + elseif ($serializables = $classAnnotations[Serializables::class][0] ?? null) { + /** @var Serializables $serializables */ if (\in_array($name, $serializables->fields)) { // 在黑名单中的字段剔除 @@ -459,24 +403,6 @@ public function hasRelation(): bool return $this->relation; } - /** - * Get 序列化注解. - */ - public function getSerializables(): ?Serializables - { - return $this->serializables; - } - - /** - * Get 提取属性注解. - * - * @return \Imi\Model\Annotation\ExtractProperty[][] - */ - public function getExtractPropertys(): array - { - return $this->extractPropertys; - } - /** * Get 类名. */ @@ -485,16 +411,6 @@ public function getClassName(): string return $this->className; } - /** - * Get 序列化注解列表. - * - * @return \Imi\Model\Annotation\Serializable[][] - */ - public function getSerializableSets(): array - { - return $this->serializableSets; - } - /** * Get 自增字段名. */ @@ -503,34 +419,6 @@ public function getAutoIncrementField(): ?string return $this->autoIncrementField; } - /** - * Get jsonNotNull 注解集合. - * - * @return \Imi\Model\Annotation\JsonNotNull[][] - */ - public function getPropertyJsonNotNullMap(): array - { - return $this->propertyJsonNotNullMap; - } - - /** - * Get JSON 序列化时的配置. - */ - public function getJsonEncode(): ?JsonEncode - { - return $this->jsonEncode; - } - - /** - * Get 定义 SQL 语句的字段列表. - * - * @return \Imi\Model\Annotation\Sql[][] - */ - public function getSqlColumns(): array - { - return $this->sqlColumns; - } - /** * Get 数据库字段名和 Column 注解映射. */ @@ -611,54 +499,42 @@ public function isBean(): bool } /** - * Get 针对字段设置的 JSON 序列化时的配置. - * - * @return JsonEncode[] - */ - public function getFieldsJsonEncode(): array - { - return $this->fieldsJsonEncode; - } - - /** - * Get jSON 反序列化时的配置. + * Get 处理后的序列化字段数组. */ - public function getJsonDecode(): ?JsonDecode + public function getParsedSerializableFieldNames(): array { - return $this->jsonDecode; + return $this->parsedSerializableFieldNames; } /** - * Get 针对字段设置的 JSON 反序列化时的配置. - * - * @return JsonDecode[] + * 是否使用表名前缀 */ - public function getFieldsJsonDecode(): array + public function isUsePrefix(): bool { - return $this->fieldsJsonDecode; + return $this->usePrefix; } /** - * Get 处理后的序列化字段数组. + * Get 是否启用增量更新. */ - public function getParsedSerializableFieldNames(): array + public function isIncrUpdate(): bool { - return $this->parsedSerializableFieldNames; + return $this->incrUpdate; } /** - * 是否使用表名前缀 + * @return \Imi\Bean\Annotation\Base[][][] */ - public function isUsePrefix(): bool + public function getPropertyAnnotations(): array { - return $this->usePrefix; + return $this->propertyAnnotations; } /** - * Get 是否启用增量更新. + * @return \Imi\Bean\Annotation\Base[][] */ - public function isIncrUpdate(): bool + public function getClassAnnotations(): array { - return $this->incrUpdate; + return $this->classAnnotations; } } diff --git a/src/Components/model/src/Model.php b/src/Components/model/src/Model.php index 56cd4efcf4..a33d29cb44 100644 --- a/src/Components/model/src/Model.php +++ b/src/Components/model/src/Model.php @@ -14,6 +14,8 @@ use Imi\Db\Query\Result; use Imi\Event\Event; use Imi\Model\Annotation\Column; +use Imi\Model\Annotation\CreateTime; +use Imi\Model\Annotation\UpdateTime; use Imi\Model\Contract\IModelQuery; use Imi\Model\Event\ModelEvents; use Imi\Model\Event\Param\AfterDeleteEventParam; @@ -814,6 +816,7 @@ private static function parseSaveData(object|array $data, string $type, ?self $o } $incrUpdate = $meta->isIncrUpdate(); $ids = $meta->getIds(); + $propertyAnnotations = $meta->getPropertyAnnotations(); foreach ($meta->getDbFields() as $dbFieldName => $item) { /** @var Column $column */ @@ -838,10 +841,11 @@ private static function parseSaveData(object|array $data, string $type, ?self $o } $columnType = $column->type; // 字段自动更新时间 - if ($column->updateTime && !$isInsert && (empty($object[$dbFieldName]) || (($originData[$dbFieldName] ?? null) === $object[$dbFieldName]))) + if ((($updateTimeAnnotation = $propertyAnnotations[UpdateTime::class][$name][0] ?? null) || $column->updateTime) && !$isInsert && (empty($object[$dbFieldName]) || (($originData[$dbFieldName] ?? null) === $object[$dbFieldName]))) { $microTime ??= microtime(true); - $value = static::parseDateTime($columnType, $column->updateTime, $microTime); + /** @var UpdateTime|null $updateTimeAnnotation */ + $value = static::parseDateTime($columnType, $updateTimeAnnotation?->timeAccuracy ?? $column->updateTime, $microTime); if (null === $value) { throw new \RuntimeException(sprintf('Column %s type is %s, can not updateTime', $dbFieldName, $columnType)); @@ -851,10 +855,11 @@ private static function parseSaveData(object|array $data, string $type, ?self $o $object[$dbFieldName] = $value; } } - elseif ($column->createTime && ($isInsert || $isSaveInsert) && empty($object[$dbFieldName])) + elseif ((($createTimeAnnotation = $propertyAnnotations[CreateTime::class][$name][0] ?? null) || $column->createTime) && ($isInsert || $isSaveInsert) && empty($object[$dbFieldName])) { $microTime ??= microtime(true); - $value = static::parseDateTime($columnType, $column->createTime, $microTime); + /** @var CreateTime|null $createTimeAnnotation */ + $value = static::parseDateTime($columnType, $createTimeAnnotation?->timeAccuracy ?? $column->createTime, $microTime); if (null === $value) { throw new \RuntimeException(sprintf('Column %s type is %s, can not createTime', $dbFieldName, $columnType)); diff --git a/src/Components/model/src/RedisModel.php b/src/Components/model/src/RedisModel.php index 840918f51f..a1d29f7ee4 100644 --- a/src/Components/model/src/RedisModel.php +++ b/src/Components/model/src/RedisModel.php @@ -9,6 +9,8 @@ use Imi\Bean\BeanFactory; use Imi\Bean\ReflectionUtil; use Imi\Model\Annotation\Column; +use Imi\Model\Annotation\JsonDecode; +use Imi\Model\Annotation\JsonEncode; use Imi\Model\Annotation\RedisEntity; use Imi\Model\Enum\RedisStorageMode; use Imi\Model\Event\ModelEvents; @@ -117,15 +119,16 @@ public function __init(array $data = []): void switch ($fieldAnnotation->type ?? self::$fieldTypeCache[$class][$k] ?? null) { case 'json': - $fieldsJsonDecode ??= $meta->getFieldsJsonDecode(); + $fieldsJsonDecode ??= $meta->getPropertyAnnotations()[JsonDecode::class] ?? []; if (isset($fieldsJsonDecode[$k][0])) { $realJsonDecode = $fieldsJsonDecode[$k][0]; } else { - $realJsonDecode = ($jsonDecode ??= ($meta->getJsonDecode() ?? false)); + $realJsonDecode = ($jsonDecode ??= ($meta->getClassAnnotations()[JsonDecode::class][0] ?? false)); } + /** @var JsonDecode|false $realJsonDecode */ if ($realJsonDecode) { $value = json_decode($v, $realJsonDecode->associative, $realJsonDecode->depth, $realJsonDecode->flags); @@ -792,15 +795,16 @@ protected function parseSaveData(array &$data): void switch ($columnAnnotation->type) { case 'json': - $fieldsJsonEncode ??= $meta->getFieldsJsonEncode(); + $fieldsJsonEncode ??= $meta->getPropertyAnnotations()[JsonEncode::class] ?? []; if (isset($fieldsJsonEncode[$name][0])) { $realJsonEncode = $fieldsJsonEncode[$name][0]; } else { - $realJsonEncode = ($jsonEncode ??= ($meta->getJsonEncode() ?? false)); + $realJsonEncode = ($jsonEncode ??= ($meta->getClassAnnotations()[JsonEncode::class][0] ?? false)); } + /** @var JsonEncode|false $realJsonEncode */ if (null === $value && $columnAnnotation->nullable) { // 当字段允许`null`时,使用原生`null`存储 diff --git a/src/Components/model/src/Relation/Query.php b/src/Components/model/src/Relation/Query.php index 3a272104f4..cf8b52e320 100644 --- a/src/Components/model/src/Relation/Query.php +++ b/src/Components/model/src/Relation/Query.php @@ -9,6 +9,7 @@ use Imi\Db\Query\Field; use Imi\Event\Event; use Imi\Model\Annotation\Relation\AutoSelect; +use Imi\Model\Annotation\Sql; use Imi\Model\BaseModel; use Imi\Model\Contract\IModelQuery; use Imi\Model\Model; @@ -871,9 +872,9 @@ private static function parseManyToManyQueryFields(string $middleModel, string $ $field->setField($name); $field->setAlias($middleTable . '_' . $name); } - foreach ($middleModelMeta->getSqlColumns() as $name => $sqlAnnotations) + foreach ($middleModelMeta->getPropertyAnnotations()[Sql::class] ?? [] as $name => $sqlAnnotations) { - /** @var \Imi\Model\Annotation\Sql $sqlAnnotation */ + /** @var Sql[] $sqlAnnotations */ $sqlAnnotation = $sqlAnnotations[0]; $fields[] = $field = new Field(); $field->useRaw(); @@ -887,9 +888,9 @@ private static function parseManyToManyQueryFields(string $middleModel, string $ $field->setTable($rightTable); $field->setField($name); } - foreach ($rightModelMeta->getSqlColumns() as $sqlAnnotations) + foreach ($rightModelMeta->getPropertyAnnotations()[Sql::class] ?? [] as $sqlAnnotations) { - /** @var \Imi\Model\Annotation\Sql $sqlAnnotation */ + /** @var Sql[] $sqlAnnotations */ $sqlAnnotation = $sqlAnnotations[0]; $fields[] = $field = new Field(); $field->useRaw(); diff --git a/src/Components/model/src/Traits/TJsonValue.php b/src/Components/model/src/Traits/TJsonValue.php index 09c9b89f5c..17e60e99c9 100644 --- a/src/Components/model/src/Traits/TJsonValue.php +++ b/src/Components/model/src/Traits/TJsonValue.php @@ -5,6 +5,8 @@ namespace Imi\Model\Traits; use Imi\Model\Annotation\Column; +use Imi\Model\Annotation\JsonDecode; +use Imi\Model\Annotation\JsonEncode; use Imi\Model\Meta; use Imi\Util\LazyArrayObject; @@ -12,8 +14,9 @@ trait TJsonValue { protected static function parseJsonInitValue(string $name, mixed $value, Column $fieldAnnotation, Meta $meta): mixed { - $fieldsJsonDecode = $meta->getFieldsJsonDecode(); - $realJsonDecode = $fieldsJsonDecode[$name][0] ?? $meta->getJsonDecode(); + $fieldsJsonDecode = $meta->getPropertyAnnotations()[JsonDecode::class] ?? []; + $realJsonDecode = $fieldsJsonDecode[$name][0] ?? $meta->getClassAnnotations()[JsonDecode::class][0] ?? false; + /** @var JsonDecode|false $realJsonDecode */ if ($realJsonDecode) { $data = json_decode((string) $value, $realJsonDecode->associative, $realJsonDecode->depth, $realJsonDecode->flags); @@ -78,15 +81,9 @@ protected static function parseJsonInitValue(string $name, mixed $value, Column protected static function parseJsonSaveValue(string $name, mixed $value, Column $fieldAnnotation, Meta $meta): mixed { - $fieldsJsonEncode = $meta->getFieldsJsonEncode(); - if (isset($fieldsJsonEncode[$name][0])) - { - $realJsonEncode = $fieldsJsonEncode[$name][0]; - } - else - { - $realJsonEncode = $meta->getJsonEncode(); - } + $fieldsJsonEncode = $meta->getPropertyAnnotations()[JsonEncode::class] ?? []; + $realJsonEncode = $fieldsJsonEncode[$name][0] ?? $meta->getClassAnnotations()[JsonEncode::class][0] ?? false; + /** @var JsonEncode|false $realJsonEncode */ if (null === $value && $fieldAnnotation->nullable) { // 当字段允许`null`时,使用原生`null`存储 diff --git a/src/Components/model/src/Traits/TModelQuery.php b/src/Components/model/src/Traits/TModelQuery.php index d8431bf188..d71e5f8ee6 100644 --- a/src/Components/model/src/Traits/TModelQuery.php +++ b/src/Components/model/src/Traits/TModelQuery.php @@ -9,6 +9,7 @@ use Imi\Db\Query\Result\ChunkByOffsetResult; use Imi\Db\Query\Result\ChunkResult; use Imi\Db\Query\Result\CursorResult; +use Imi\Model\Annotation\Sql; use Imi\Model\Meta; use Imi\Model\Model; use Imi\Model\ModelQueryResult; @@ -63,8 +64,9 @@ private function queryPreProcess(): void { /** @var \Imi\Model\Meta $meta */ $meta = $this->modelClass::__getMeta(); - if ($sqlColumns = $meta->getSqlColumns()) + if ($sqlColumns = $meta->getPropertyAnnotations()[Sql::class] ?? []) { + /** @var Sql[][] $sqlColumns */ $this->field($meta->getTableName() . '.*'); $fields = $meta->getFields(); foreach ($sqlColumns as $name => $sqlAnnotations) diff --git a/src/Components/model/tests/Model/CreateTime.php b/src/Components/model/tests/Model/CreateTime.php index f562de0122..060c659b8c 100644 --- a/src/Components/model/tests/Model/CreateTime.php +++ b/src/Components/model/tests/Model/CreateTime.php @@ -17,7 +17,9 @@ class CreateTime extends CreateTimeBase /** * date. */ - #[Column(name: 'date', type: 'date', length: 0, default: '', createTime: true)] + #[Column(name: 'date', type: 'date', length: 0, default: '')] + // 测试 CreateTime 注解 + #[\Imi\Model\Annotation\CreateTime()] protected ?string $date = null; /** diff --git a/src/Components/model/tests/Model/UpdateTime.php b/src/Components/model/tests/Model/UpdateTime.php index f178fcb8b0..c7415f82c0 100644 --- a/src/Components/model/tests/Model/UpdateTime.php +++ b/src/Components/model/tests/Model/UpdateTime.php @@ -17,7 +17,9 @@ class UpdateTime extends UpdateTimeBase /** * date. */ - #[Column(name: 'date', type: 'date', length: 0, default: '', updateTime: true)] + #[Column(name: 'date', type: 'date', length: 0, default: '')] + // 测试 UpdateTime 注解 + #[\Imi\Model\Annotation\UpdateTime()] protected ?string $date = null; /** From 4907ff9ab87b3a8832c5d18f6125d8608fe314b2 Mon Sep 17 00:00:00 2001 From: Yurun Date: Sat, 1 Jun 2024 21:41:01 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E4=B8=AD=E5=BF=83?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20createConnection()=20=E6=96=B9=E6=B3=95?= =?UTF-8?q?=EF=BC=8C=E9=87=8D=E6=9E=84=20Imi\Db\Db::getNewInstance()=20(#6?= =?UTF-8?q?99)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/base/version/2.1-3.0.md | 4 ++ .../src/ConnectionCenter.php | 30 +++++++++++ .../src/Facade/ConnectionCenter.php | 1 + .../tests/Tests/ConnectionCenterTest.php | 14 +++++ src/Components/database/src/Db.php | 31 ++++++++--- .../src/Listener/CheckPoolResource.php | 52 ------------------- 6 files changed, 72 insertions(+), 60 deletions(-) delete mode 100644 src/Components/database/src/Listener/CheckPoolResource.php diff --git a/doc/base/version/2.1-3.0.md b/doc/base/version/2.1-3.0.md index 032f4be6d8..e0f5748c21 100644 --- a/doc/base/version/2.1-3.0.md +++ b/doc/base/version/2.1-3.0.md @@ -81,6 +81,10 @@ return [ * 事件名称规则统一改为全小写,为保持兼容请[参考文档](/v3.0/event/index.html#3.0%20兼容性) +### 数据库 + +* `Imi\Db\Db::getNewInstance()` 返回值改为 `Imi\ConnectionCenter\Contract\IConnection` + ### 模型 * UUID 发号器的 `type` 类型改为枚举,大小写有所变化 diff --git a/src/Components/connection-center/src/ConnectionCenter.php b/src/Components/connection-center/src/ConnectionCenter.php index d44a39ce72..07856b6885 100644 --- a/src/Components/connection-center/src/ConnectionCenter.php +++ b/src/Components/connection-center/src/ConnectionCenter.php @@ -74,11 +74,23 @@ public function getConnectionManagers(): array return $this->connectionManagers; } + /** + * 获取连接. + * + * 需要调用 getInstance() 获取实际的对象进行操作. + * + * 需要自行管理连接生命周期,连接对象释放即归还连接池. + */ public function getConnection(string $name): IConnection { return $this->getConnectionManager($name)->getConnection(); } + /** + * 获取连接. + * + * 自动管理生命周期,当前上下文结束时自动释放. + */ public function getRequestContextConnection(string $name): IConnection { $requestContext = RequestContext::getContext(); @@ -119,4 +131,22 @@ public function getRequestContextConnection(string $name): IConnection return $connection; } + + /** + * 创建新的连接. + * + * 返回的连接是实际的对象,不受连接管理器管理生命周期. + */ + public function createConnection(?string $name = null, bool $autoConnect = true): mixed + { + $driver = self::getConnectionManager($name)->getDriver(); + $instance = $driver->createInstance(); + + if ($autoConnect) + { + return $driver->connect($instance); + } + + return $instance; + } } diff --git a/src/Components/connection-center/src/Facade/ConnectionCenter.php b/src/Components/connection-center/src/Facade/ConnectionCenter.php index 3feb683f6d..827e803c7f 100644 --- a/src/Components/connection-center/src/Facade/ConnectionCenter.php +++ b/src/Components/connection-center/src/Facade/ConnectionCenter.php @@ -15,6 +15,7 @@ * @method static IConnectionManager[] getConnectionManagers() * @method static \Imi\ConnectionCenter\Contract\IConnection getConnection(string $name) * @method static \Imi\ConnectionCenter\Contract\IConnection getRequestContextConnection(string $name) + * @method static mixed createConnection(?string $name = NULL, bool $autoConnect = true) */ #[ \Imi\Facade\Annotation\Facade(class: \Imi\ConnectionCenter\AppConnectionCenter::class) diff --git a/src/Components/connection-center/tests/Tests/ConnectionCenterTest.php b/src/Components/connection-center/tests/Tests/ConnectionCenterTest.php index 238a27a520..1ad8077c03 100644 --- a/src/Components/connection-center/tests/Tests/ConnectionCenterTest.php +++ b/src/Components/connection-center/tests/Tests/ConnectionCenterTest.php @@ -198,6 +198,20 @@ public function testRequestContextDestroy(): void } } + public function testCreateConnection(): void + { + foreach (self::$names as $name) + { + $connection1 = self::$connectionCenter->createConnection($name); + $this->assertTrue($connection1->connected); + + $connection2 = self::$connectionCenter->createConnection($name, false); + $this->assertFalse($connection2->connected); + + $this->assertTrue(self::$connectionCenter->createConnection($name) !== self::$connectionCenter->createConnection($name)); + } + } + /** * @depends testNewInstance */ diff --git a/src/Components/database/src/Db.php b/src/Components/database/src/Db.php index 71569d9dd7..d250479f31 100644 --- a/src/Components/database/src/Db.php +++ b/src/Components/database/src/Db.php @@ -5,6 +5,7 @@ namespace Imi\Db; use Imi\Config; +use Imi\ConnectionCenter\Contract\IConnection; use Imi\ConnectionCenter\Facade\ConnectionCenter; use Imi\Db\ConnectionCenter\DatabaseDriverConfig; use Imi\Db\Interfaces\IDb; @@ -19,28 +20,42 @@ class Db use \Imi\Util\Traits\TStaticClass; /** - * 获取新的数据库连接实例. + * 获取数据库连接实例,每个上下文中共用一个. * * @param string|null $poolName 连接池名称 * @param int $queryType 查询类型 */ - public static function getNewInstance(?string $poolName = null, int $queryType = QueryType::WRITE): IDb + public static function getInstance(?string $poolName = null, int $queryType = QueryType::WRITE): IDb { - $driver = ConnectionCenter::getConnectionManager(self::parsePoolName($poolName, $queryType))->getDriver(); - $instance = $driver->createInstance(); + return ConnectionCenter::getRequestContextConnection(self::parsePoolName($poolName, $queryType))->getInstance(); + } - return $driver->connect($instance); + /** + * 创建新的数据库连接实例. + * + * @param string|null $poolName 连接池名称 + * @param int $queryType 查询类型 + */ + public static function createInstance(?string $poolName = null, int $queryType = QueryType::WRITE): IDb + { + return ConnectionCenter::createConnection(self::parsePoolName($poolName, $queryType)); } /** - * 获取数据库连接实例,每个RequestContext中共用一个. + * 获取新的数据库连接实例. + * + * 返回的是连接池连接对象,需调用 `getInstance()` 获取实际的对象进行操作. + * + * 连接对象释放即断开连接,操作期间需要保证连接对象不被释放. + * + * 如果不是特别必要,不推荐使用此方法!!! * * @param string|null $poolName 连接池名称 * @param int $queryType 查询类型 */ - public static function getInstance(?string $poolName = null, int $queryType = QueryType::WRITE): IDb + public static function getNewInstance(?string $poolName = null, int $queryType = QueryType::WRITE): IConnection { - return ConnectionCenter::getRequestContextConnection(self::parsePoolName($poolName, $queryType))->getInstance(); + return ConnectionCenter::getConnection(self::parsePoolName($poolName, $queryType)); } /** diff --git a/src/Components/database/src/Listener/CheckPoolResource.php b/src/Components/database/src/Listener/CheckPoolResource.php deleted file mode 100644 index 520ae3ed77..0000000000 --- a/src/Components/database/src/Listener/CheckPoolResource.php +++ /dev/null @@ -1,52 +0,0 @@ -result; - foreach ($connections as $name => $_) - { - if (!PoolManager::exists($name)) - { - try - { - $db = Db::getNewInstance($name); - if ($db->isConnected() && $db->ping()) - { - $db->close(); - } - else - { - $result = false; - } - } - catch (\Throwable $th) - { - Log::error($th); - Log::error(sprintf('The Db [%s] are not available', $name)); - $result = false; - } - } - } - } - } -} From e93845615d5e8e93c6fadda6bee721702295141a Mon Sep 17 00:00:00 2001 From: Yurun Date: Mon, 10 Jun 2024 10:09:39 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=B5=8B=E8=AF=95=20(#70?= =?UTF-8?q?3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 修复每日测试的 Swoole 编译 * 修复测试 * test * test --- .github/php.dockerfile | 11 +++++++++-- .github/workflows/ci.yml | 3 ++- .github/workflows/daily-test.yml | 8 ++++++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.github/php.dockerfile b/.github/php.dockerfile index cc280ffd6f..3bafc62136 100644 --- a/.github/php.dockerfile +++ b/.github/php.dockerfile @@ -8,7 +8,7 @@ ARG SWOOLE_VERSION COPY script/ /tmp/script RUN set -eux \ - && apt-get update && apt-get -y install procps libpq-dev unzip git libzip-dev libevent-dev libssl-dev libicu-dev libc-ares-dev libcurl4-openssl-dev unixodbc-dev libsqlite3-dev \ + && apt-get update && apt-get -y install procps libpq-dev unzip git libzip-dev libevent-dev libssl-dev libicu-dev libc-ares-dev libcurl4-openssl-dev unixodbc-dev libsqlite3-dev libbrotli-dev \ && docker-php-ext-install -j$(nproc) bcmath mysqli pdo_mysql pdo_pgsql pcntl sockets intl zip \ && (php --ri redis || (pecl install redis && docker-php-ext-enable redis)) \ && pecl install inotify \ @@ -18,6 +18,13 @@ RUN set -eux \ && pecl install apcu \ && docker-php-ext-enable apcu \ && curl -sfL https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer && chmod +x /usr/bin/composer \ - && curl -L -o swoole.tar.gz https://github.com/swoole/swoole-src/archive/${SWOOLE_VERSION}.tar.gz && mkdir -p swoole && tar -xzf swoole.tar.gz -C swoole --strip-components=1 && rm swoole.tar.gz && cd swoole && ((stat ./make.sh && ./make.sh) || (stat ./scripts/make.sh && ./scripts/make.sh)) && cd - && docker-php-ext-enable swoole \ + && curl -L -o swoole.tar.gz https://github.com/swoole/swoole-src/archive/${SWOOLE_VERSION}.tar.gz && mkdir -p swoole && tar -xzf swoole.tar.gz -C swoole --strip-components=1 && rm swoole.tar.gz && cd swoole && ((stat ./make.sh && ./make.sh) || (phpize && ./configure --enable-openssl \ + --enable-sockets \ + --enable-mysqlnd \ + --enable-swoole-curl \ + --enable-cares \ + --enable-swoole-pgsql \ + --with-swoole-odbc=unixODBC,/usr \ + --enable-swoole-sqlite && make -j install)) && cd - && docker-php-ext-enable swoole \ && bash /tmp/script/swoole_postgresql.sh ${POSTGRESQL_VERSION} \ && echo "zend_extension=opcache.so" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2792781342..68b2e3b1dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -355,7 +355,8 @@ jobs: # MacOS Arm64 下需要下面的修复,否则无法编译成功 - name: Fix include run: | - sudo ln -s $(brew --prefix pcre2)/include/pcre2.h /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ + sudo mkdir -p /usr/local/include + sudo ln -s $(brew --prefix pcre2)/include/pcre2.h /usr/local/include/ - name: Get Openssl Dir id: opecssl-dir run: echo "path=$(brew --prefix openssl@1.1)" >> $GITHUB_OUTPUT diff --git a/.github/workflows/daily-test.yml b/.github/workflows/daily-test.yml index a90c8bb8f6..b3bf8d9b7d 100644 --- a/.github/workflows/daily-test.yml +++ b/.github/workflows/daily-test.yml @@ -6,9 +6,15 @@ on: push: paths: - ".github/workflows/daily-test.yml" + - ".github/docker-compose.yml" + - ".github/php.dockerfile" + - ".github/actions/ci-prepare" pull_request: paths: - ".github/workflows/daily-test.yml" + - ".github/docker-compose.yml" + - ".github/php.dockerfile" + - ".github/actions/ci-prepare" jobs: daily-test-3_0: @@ -33,8 +39,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - ref: "3.0" - name: Cache dependencies uses: actions/cache@v4 with: