From 3893f77f81b89e19d4a670b47f6d748546552345 Mon Sep 17 00:00:00 2001 From: Yurun Date: Mon, 13 Nov 2023 10:20:04 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20ConnectionContextStore?= =?UTF-8?q?=20=E5=88=9D=E5=A7=8B=E5=8C=96=20(#642)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../swoole/src/Server/ConnectionContext/Listener/AppInit.php | 2 +- src/Server/ConnectionContext/StoreHandler.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/swoole/src/Server/ConnectionContext/Listener/AppInit.php b/src/Components/swoole/src/Server/ConnectionContext/Listener/AppInit.php index 0b3664f801..f739322807 100644 --- a/src/Components/swoole/src/Server/ConnectionContext/Listener/AppInit.php +++ b/src/Components/swoole/src/Server/ConnectionContext/Listener/AppInit.php @@ -41,7 +41,7 @@ public function handle(EventParam $e): void { RequestContext::set('server', $server); // @phpstan-ignore-next-line - $server->getBean('ConnectionContextStore')->init(); + $server->getBean('ConnectionContextStore'); if (Imi::getClassPropertyValue('ServerGroup', 'status')) { /** @var \Imi\Server\Group\Handler\IGroupHandler $groupHandler */ diff --git a/src/Server/ConnectionContext/StoreHandler.php b/src/Server/ConnectionContext/StoreHandler.php index 786f80aedd..5f2e542b87 100644 --- a/src/Server/ConnectionContext/StoreHandler.php +++ b/src/Server/ConnectionContext/StoreHandler.php @@ -31,7 +31,7 @@ class StoreHandler implements IHandler */ private ?IHandler $handler = null; - public function init(): void + public function __init(): void { $this->getHandler(); } From dd9c50a458ff9dc6f72f2b0f0272f6ea0ab99490 Mon Sep 17 00:00:00 2001 From: Yurun Date: Mon, 13 Nov 2023 10:55:09 +0800 Subject: [PATCH 2/9] =?UTF-8?q?v2.1=20=E4=B8=AD=E5=B7=B2=E7=BB=8F=E6=A0=87?= =?UTF-8?q?=E8=AE=B0=E4=B8=BA=20deprecated=20=E7=9A=84=E5=9C=A8=20v3.0=20?= =?UTF-8?q?=E5=BA=9F=E5=BC=83=20(#641)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 废弃 imiGetEnv() * 废弃 Cache 中的类型检查,改为原生类型 * 废弃 gRPC 旧的 Server 相关类 * 废弃 Swoole MySQL 客户端,建议使用 PDO 和 mysqli * 废弃 ErrorLog::onException() * 废弃 ExtractData 注解 * 废弃 Imi\Util\DateTime::getLastWeek(),错误的命名 * 废弃连接池类的 createResource() 方法,改为 createNewResource() * 废弃 Imi\Pool\ResourceConfigMode::TURN * 废弃 Query::chunkEach() * 废弃 Query::alias() * 更新文档 * 重构代码 * 废弃 Query::alias() * 处理 TODO --- doc/base/version/2.1-3.0.md | 26 ++ doc/components/db/config.md | 6 - doc/components/db/index.md | 4 - doc/components/db/mysql.md | 4 - doc/components/httpserver/request.md | 24 - doc/components/httpserver/validation.md | 9 - doc/components/orm/RDModel.md | 4 - doc/utils/functions.md | 8 - src/Cache/Handler/Base.php | 23 - src/Cache/Handler/File.php | 7 - src/Cache/Handler/Memory.php | 3 - src/Cache/Handler/Redis.php | 10 - src/Cache/Handler/RedisHash.php | 6 - src/Cache/Handler/RequestContext.php | 3 - .../amqp/src/Pool/AMQPCoroutinePool.php | 8 - src/Components/amqp/src/Pool/AMQPSyncPool.php | 8 - src/Components/grpc/composer.json | 3 +- .../Error/DefaultGrpcErrorHandler.php | 12 - .../src/old-server/Error/GrpcErrorHandler.php | 12 - src/Components/grpc/src/old-server/Server.php | 12 - .../kafka/src/Pool/KafkaCoroutinePool.php | 8 - .../kafka/src/Pool/KafkaSyncPool.php | 8 - .../Client/Pool/RpcClientCoroutinePool.php | 8 - .../rpc/src/Client/Pool/RpcClientSyncPool.php | 8 - .../shared-memory/src/Pool/ClientPool.php | 8 - .../swoole/src/Db/Driver/Swoole/Driver.php | 418 ------------------ .../swoole/src/Db/Driver/Swoole/Statement.php | 388 ---------------- .../swoole/src/Db/Pool/CoroutineDbPool.php | 8 - src/Components/swoole/tests/phpunit.xml | 3 - .../Performance/SwooleMysqlDbTest.php | 18 - .../unit/Component/Tests/Db/Swoole/DbTest.php | 2 +- .../Tests/Db/Swoole/QueryCurdTest.php | 2 +- .../tests/unit/Component/config/config.php | 23 - .../ApiServer/Controller/IndexController.php | 13 - .../unit/HttpServer/Tests/RequestTest.php | 14 - src/Db/Pool/SyncDbPool.php | 8 - src/Db/Query/Interfaces/IQuery.php | 16 - src/Db/Query/Query.php | 305 +------------ src/HttpValidate/Annotation/ExtractData.php | 15 - src/Log/ErrorLog.php | 12 +- src/Model/Annotation/DDL.php | 3 - src/Model/Traits/TJsonValue.php | 14 +- src/Model/Traits/TListValue.php | 12 +- src/Model/Traits/TModelQuery.php | 10 - src/Model/Traits/TSetValue.php | 12 +- src/Pool/BasePool.php | 12 +- src/Pool/ResourceConfigMode.php | 7 - src/Redis/Traits/TRedisPool.php | 2 +- src/Server/Http/Annotation/ExtractData.php | 32 -- src/Server/Http/Listener/HttpRouteInit.php | 15 - src/Util/ArrayData.php | 8 - src/Util/DateTime.php | 16 - src/functions.php | 11 - tests/unit/Component/Tests/EnvTest.php | 17 - 54 files changed, 52 insertions(+), 1596 deletions(-) delete mode 100644 src/Components/grpc/src/old-server/Error/DefaultGrpcErrorHandler.php delete mode 100644 src/Components/grpc/src/old-server/Error/GrpcErrorHandler.php delete mode 100644 src/Components/grpc/src/old-server/Server.php delete mode 100644 src/Components/swoole/src/Db/Driver/Swoole/Driver.php delete mode 100644 src/Components/swoole/src/Db/Driver/Swoole/Statement.php delete mode 100644 src/Components/swoole/tests/unit/Component/Performance/SwooleMysqlDbTest.php delete mode 100644 src/HttpValidate/Annotation/ExtractData.php delete mode 100644 src/Server/Http/Annotation/ExtractData.php diff --git a/doc/base/version/2.1-3.0.md b/doc/base/version/2.1-3.0.md index 6ea28ea19f..fb29d84c6a 100644 --- a/doc/base/version/2.1-3.0.md +++ b/doc/base/version/2.1-3.0.md @@ -122,3 +122,29 @@ return [ `Imi\Tool\Annotation\Tool` => `Imi\Cli\Annotation\Command` `Imi\Tool\ArgType` => `Imi\Cli\ArgType` + +* 废弃 `Query::alias()` + +* 废弃 `Query::chunkEach()`,改为: + +```php +$query->chunkById($count, $column, $alias)->each(); +// 或 +$query->chunkByOffset($limit)->each(); +``` + +* 废弃 `Imi\Pool\ResourceConfigMode::TURN` 改为 `Imi\Pool\ResourceConfigMode::ROUND_ROBIN` + +* 废弃连接池类的 `createResource()` 方法,改为 `createNewResource()`,影响自定义连接池 + +* 废弃 `Imi\Util\DateTime::getLastWeek()`,错误的命名,改为 `Imi\Util\DateTime::getPrevWeek()` + +* 废弃 `ExtractData` 注解,建议使用 `RequestParam` + +* 废弃 `ErrorLog::onException()`,建议使用 `Imi\Log\Log::error()` + +* 废弃 Swoole MySQL 客户端,建议使用 PDO 和 mysqli + +* 废弃 gRPC 旧的 Server 相关类 + +* 废弃 `imiGetEnv()`、建议使用 `Imi\env()` diff --git a/doc/components/db/config.md b/doc/components/db/config.md index 6ddf6b6584..e0b717a0d8 100644 --- a/doc/components/db/config.md +++ b/doc/components/db/config.md @@ -70,8 +70,6 @@ return [ // 'dbClass' => 'PdoMysqlDriver', // 使用 hook mysqli 驱动 // 'dbClass' => 'MysqliDriver', - // 使用 Swoole MySQL 驱动 - // 'dbClass' => 'SwooleMysqlDriver', // 数据库连接后,执行初始化的 SQL // 'initSqls' => [ // 'select 1', @@ -137,8 +135,6 @@ return [ // 'dbClass' => 'PdoMysqlDriver', // 使用 hook mysqli 驱动 // 'dbClass' => 'MysqliDriver', - // 使用 Swoole MySQL 驱动 - // 'dbClass' => 'SwooleMysqlDriver', // 数据库连接后,执行初始化的 SQL // 'initSqls' => [ // 'select 1', @@ -183,8 +179,6 @@ return [ // 'dbClass' => 'PdoMysqlDriver', // 使用 hook mysqli 驱动 // 'dbClass' => 'MysqliDriver', - // 使用 Swoole MySQL 驱动 - // 'dbClass' => 'SwooleMysqlDriver', // 数据库连接后,执行初始化的 SQL // 'initSqls' => [ // 'select 1', diff --git a/doc/components/db/index.md b/doc/components/db/index.md index a8747eae58..35ed76cddf 100644 --- a/doc/components/db/index.md +++ b/doc/components/db/index.md @@ -941,10 +941,6 @@ foreach (Db::query()->table('tb_test')->chunkByOffset(10)->each() as $row) } ``` -##### chunkEach - -> 该方法已弃用并计划`3.0`移除,请使用`chunkById()->each()`or`chunkByOffset()->each()`替代。 - #### 游标查询 游标查询能对于查询大结果集时能有效节约应用内存消耗,对于数据库的消耗与`select`无差别。 diff --git a/doc/components/db/mysql.md b/doc/components/db/mysql.md index c2908f1dcd..271335711b 100644 --- a/doc/components/db/mysql.md +++ b/doc/components/db/mysql.md @@ -11,7 +11,3 @@ ### MysqliDriver 基于 MySQLi 实现,支持所有环境,支持 Swoole 协程。 - -### SwooleMysqlDriver - -只支持 Swoole 环境 diff --git a/doc/components/httpserver/request.md b/doc/components/httpserver/request.md index 30e5a9aca7..a5ab7c84aa 100644 --- a/doc/components/httpserver/request.md +++ b/doc/components/httpserver/request.md @@ -330,27 +330,3 @@ public function requestParam2( ]; } ``` - -### ExtractData 注解 - -将在 imi 3.0 中废弃,推荐使用 `RequestParam` 注解。 - -**代码示例:** - -```php -/** - * http参数验证测试 - * - * @return void - */ -#[ - Action, - ExtractData(name: '$get.id', to: 'id'), - ExtractData(name: '$get.name', to: 'name'), - ExtractData(name: '$get.age', to: 'age'), -] -public function httpValidation($id, $name, $age) -{ - return compact('id', 'name', 'age'); -} -``` diff --git a/doc/components/httpserver/validation.md b/doc/components/httpserver/validation.md index 15e663a7e3..113f53deaf 100644 --- a/doc/components/httpserver/validation.md +++ b/doc/components/httpserver/validation.md @@ -18,12 +18,6 @@ 在 HTTP 验证器场景下,不推荐在验证注解上指定 `default` 参数,而是应该直接给方法参数加上默认值。 -## ExtractData - -还有一个`ExtractData`注解,它可以把`get/post/body`中的参数导出到`action`方法的参数中。 - -`ExtractData`注解可以独立使用,不依赖`HttpValidation`注解,但只能在控制器中使用。 - ## 示例 ```php @@ -40,9 +34,6 @@ Required(name: '$get.name', message: '用户姓名为必传参数'), Text(name: '$get.name', min: 2, message: '用户姓名长度不得少于2位'), Required(name: '$get.age'), - ExtractData(name: '$get.id', to: 'id'), - ExtractData(name: '$get.name', to: 'name'), - ExtractData(name: '$get.age', to: 'age'), ] public function httpValidation($id, $name, $age = -1) { diff --git a/doc/components/orm/RDModel.md b/doc/components/orm/RDModel.md index 431b7bb672..f8d1eec393 100644 --- a/doc/components/orm/RDModel.md +++ b/doc/components/orm/RDModel.md @@ -393,10 +393,6 @@ foreach (TestModel::query()->chunkByOffset(10)->each() as $row) } ``` -##### chunkEach - -> 该方法已弃用并计划`3.0`移除,请使用`chunkById()->each()`or`chunkByOffset()->each()`替代。 - #### 游标查询 游标查询能对于查询大结果集时能有效节约应用内存消耗,对于数据库的消耗与`select`无差别。。 diff --git a/doc/utils/functions.md b/doc/utils/functions.md index caf3b76fe2..e167eb0937 100644 --- a/doc/utils/functions.md +++ b/doc/utils/functions.md @@ -49,14 +49,6 @@ function test($a) test($callable); ``` -## imiGetEnv - -获取环境变量值 - -定义:`imiGetEnv($varname = null, $default = null, $localOnly = false);` - -> 将在 imi v3.0.0 废弃,请使用 `Imi\env()` - ## Imi\env 获取环境变量值 diff --git a/src/Cache/Handler/Base.php b/src/Cache/Handler/Base.php index 8f5b644769..002db8eb59 100644 --- a/src/Cache/Handler/Base.php +++ b/src/Cache/Handler/Base.php @@ -5,7 +5,6 @@ namespace Imi\Cache\Handler; use Imi\App; -use Imi\Cache\InvalidArgumentException; use Imi\RequestContext; use Psr\SimpleCache\CacheInterface; @@ -65,26 +64,4 @@ protected function decode(string $data): mixed return App::getBean($this->formatHandlerClass)->decode($data); } } - - /** - * 检查key格式. - * - * @deprecated 3.0 - */ - protected function checkKey(string $key): void - { - } - - /** - * 检查值是否是数组或Traversable. - * - * @deprecated 3.0 - */ - protected function checkArrayOrTraversable(mixed $values): void - { - if (!\is_array($values) && !$values instanceof \Traversable) - { - throw new InvalidArgumentException('Invalid keys'); - } - } } diff --git a/src/Cache/Handler/File.php b/src/Cache/Handler/File.php index 766d28d0b3..3c9e4f8eed 100644 --- a/src/Cache/Handler/File.php +++ b/src/Cache/Handler/File.php @@ -36,7 +36,6 @@ class File extends Base */ public function get(string $key, mixed $default = null): mixed { - $this->checkKey($key); $fileName = $this->getFileName($key); // 缓存文件不存在 if (!is_file($fileName)) @@ -86,7 +85,6 @@ public function get(string $key, mixed $default = null): mixed */ public function set(string $key, mixed $value, null|int|\DateInterval $ttl = null): bool { - $this->checkKey($key); $fileName = $this->getFileName($key); // 自动建目录 $dir = \dirname($fileName); @@ -135,7 +133,6 @@ public function set(string $key, mixed $value, null|int|\DateInterval $ttl = nul */ public function delete(string $key): bool { - $this->checkKey($key); $fileName = $this->getFileName($key); if (is_file($fileName)) { @@ -180,7 +177,6 @@ public function clear(): bool */ public function getMultiple(iterable $keys, mixed $default = null): iterable { - $this->checkArrayOrTraversable($keys); $result = []; foreach ($keys as $key) { @@ -195,7 +191,6 @@ public function getMultiple(iterable $keys, mixed $default = null): iterable */ public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null): bool { - $this->checkArrayOrTraversable($values); $result = true; // ttl 支持 \DateInterval 格式 if ($ttl instanceof \DateInterval) @@ -215,7 +210,6 @@ public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null */ public function deleteMultiple(iterable $keys): bool { - $this->checkArrayOrTraversable($keys); $result = true; foreach ($keys as $key) { @@ -230,7 +224,6 @@ public function deleteMultiple(iterable $keys): bool */ public function has(string $key): bool { - $this->checkKey($key); $fileName = $this->getFileName($key); // 缓存文件不存在 if (!is_file($fileName)) diff --git a/src/Cache/Handler/Memory.php b/src/Cache/Handler/Memory.php index 6ddeb26f5a..b04a5a1911 100644 --- a/src/Cache/Handler/Memory.php +++ b/src/Cache/Handler/Memory.php @@ -70,7 +70,6 @@ public function clear(): bool */ public function getMultiple(iterable $keys, mixed $default = null): iterable { - $this->checkArrayOrTraversable($keys); $object = self::$storage; $result = []; foreach ($keys as $key) @@ -86,7 +85,6 @@ public function getMultiple(iterable $keys, mixed $default = null): iterable */ public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null): bool { - $this->checkArrayOrTraversable($values); // ttl 支持 \DateInterval 格式 if ($ttl instanceof \DateInterval) { @@ -106,7 +104,6 @@ public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null */ public function deleteMultiple(iterable $keys): bool { - $this->checkArrayOrTraversable($keys); $object = self::$storage; foreach ($keys as $key) { diff --git a/src/Cache/Handler/Redis.php b/src/Cache/Handler/Redis.php index 9bcd8ec83e..7999a37729 100644 --- a/src/Cache/Handler/Redis.php +++ b/src/Cache/Handler/Redis.php @@ -31,7 +31,6 @@ class Redis extends Base */ public function get(string $key, mixed $default = null): mixed { - $this->checkKey($key); $result = ImiRedis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->get($this->parseKey($key)), $this->poolName, true); if (false === $result) { @@ -48,7 +47,6 @@ public function get(string $key, mixed $default = null): mixed */ public function set(string $key, mixed $value, null|int|\DateInterval $ttl = null): bool { - $this->checkKey($key); // ttl 支持 \DateInterval 格式 if ($ttl instanceof \DateInterval) { @@ -63,8 +61,6 @@ public function set(string $key, mixed $value, null|int|\DateInterval $ttl = nul */ public function delete(string $key): bool { - $this->checkKey($key); - return (bool) ImiRedis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->del($this->parseKey($key)) > 0, $this->poolName, true); } @@ -81,7 +77,6 @@ public function clear(): bool */ public function getMultiple(iterable $keys, mixed $default = null): iterable { - $this->checkArrayOrTraversable($keys); foreach ($keys as &$key) { $key = $this->parseKey($key); @@ -111,7 +106,6 @@ public function getMultiple(iterable $keys, mixed $default = null): iterable */ public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null): bool { - $this->checkArrayOrTraversable($values); if ($values instanceof \Traversable) { $setValues = clone $values; @@ -158,8 +152,6 @@ public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null */ public function deleteMultiple(iterable $keys): bool { - $this->checkArrayOrTraversable($keys); - foreach ($keys as &$key) { $key = $this->parseKey($key); @@ -173,8 +165,6 @@ public function deleteMultiple(iterable $keys): bool */ public function has(string $key): bool { - $this->checkKey($key); - return (bool) ImiRedis::use(fn (\Imi\Redis\RedisHandler $redis) => $redis->exists($this->parseKey($key)), $this->poolName, true); } diff --git a/src/Cache/Handler/RedisHash.php b/src/Cache/Handler/RedisHash.php index 75fd45bf09..dc87f648ee 100644 --- a/src/Cache/Handler/RedisHash.php +++ b/src/Cache/Handler/RedisHash.php @@ -111,8 +111,6 @@ public function clear(): bool */ public function getMultiple(iterable $keys, mixed $default = null): iterable { - $this->checkArrayOrTraversable($keys); - $keysMembers = []; foreach ($keys as $key) { @@ -152,8 +150,6 @@ public function getMultiple(iterable $keys, mixed $default = null): iterable */ public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null): bool { - $this->checkArrayOrTraversable($values); - if ($values instanceof \Traversable) { $_setValues = clone $values; @@ -193,8 +189,6 @@ public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null */ public function deleteMultiple(iterable $keys): bool { - $this->checkArrayOrTraversable($keys); - $keysMembers = []; foreach ($keys as $key) { diff --git a/src/Cache/Handler/RequestContext.php b/src/Cache/Handler/RequestContext.php index 085e169c30..103fb275c2 100644 --- a/src/Cache/Handler/RequestContext.php +++ b/src/Cache/Handler/RequestContext.php @@ -65,7 +65,6 @@ public function clear(): bool */ public function getMultiple(iterable $keys, mixed $default = null): iterable { - $this->checkArrayOrTraversable($keys); $object = $this->getObject(); $result = []; foreach ($keys as $key) @@ -81,7 +80,6 @@ public function getMultiple(iterable $keys, mixed $default = null): iterable */ public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null): bool { - $this->checkArrayOrTraversable($values); // ttl 支持 \DateInterval 格式 if ($ttl instanceof \DateInterval) { @@ -101,7 +99,6 @@ public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null */ public function deleteMultiple(iterable $keys): bool { - $this->checkArrayOrTraversable($keys); $object = $this->getObject(); foreach ($keys as $key) { diff --git a/src/Components/amqp/src/Pool/AMQPCoroutinePool.php b/src/Components/amqp/src/Pool/AMQPCoroutinePool.php index cde3e597f8..02aa4704e9 100644 --- a/src/Components/amqp/src/Pool/AMQPCoroutinePool.php +++ b/src/Components/amqp/src/Pool/AMQPCoroutinePool.php @@ -22,14 +22,6 @@ public function __construct(string $name, \Imi\Pool\Interfaces\IPoolConfig $conf $this->initUriResourceConfig(); } - /** - * {@inheritDoc} - */ - protected function createResource(): IPoolResource - { - return $this->createNewResource(); - } - /** * {@inheritDoc} */ diff --git a/src/Components/amqp/src/Pool/AMQPSyncPool.php b/src/Components/amqp/src/Pool/AMQPSyncPool.php index 3b20cfc731..cc16bd000c 100644 --- a/src/Components/amqp/src/Pool/AMQPSyncPool.php +++ b/src/Components/amqp/src/Pool/AMQPSyncPool.php @@ -23,14 +23,6 @@ public function __construct(string $name, \Imi\Pool\Interfaces\IPoolConfig $conf $this->initUriResourceConfig(); } - /** - * {@inheritDoc} - */ - protected function createResource(): IPoolResource - { - return $this->createNewResource(); - } - /** * {@inheritDoc} */ diff --git a/src/Components/grpc/composer.json b/src/Components/grpc/composer.json index 206320f5ba..0cb4c0548e 100644 --- a/src/Components/grpc/composer.json +++ b/src/Components/grpc/composer.json @@ -11,8 +11,7 @@ "require-dev": {}, "autoload": { "psr-4": { - "Imi\\Grpc\\": "src/", - "Imi\\Server\\Grpc\\": "src/old-server/" + "Imi\\Grpc\\": "src/" } }, "autoload-dev": { diff --git a/src/Components/grpc/src/old-server/Error/DefaultGrpcErrorHandler.php b/src/Components/grpc/src/old-server/Error/DefaultGrpcErrorHandler.php deleted file mode 100644 index 08001e0c7a..0000000000 --- a/src/Components/grpc/src/old-server/Error/DefaultGrpcErrorHandler.php +++ /dev/null @@ -1,12 +0,0 @@ -initUriResourceConfig(); } - /** - * {@inheritDoc} - */ - protected function createResource(): IPoolResource - { - return $this->createNewResource(); - } - /** * {@inheritDoc} */ diff --git a/src/Components/kafka/src/Pool/KafkaSyncPool.php b/src/Components/kafka/src/Pool/KafkaSyncPool.php index 43d06fdf38..4bec3fa42d 100644 --- a/src/Components/kafka/src/Pool/KafkaSyncPool.php +++ b/src/Components/kafka/src/Pool/KafkaSyncPool.php @@ -24,14 +24,6 @@ public function __construct(string $name, \Imi\Pool\Interfaces\IPoolConfig $conf $this->initUriResourceConfig(); } - /** - * {@inheritDoc} - */ - protected function createResource(): IPoolResource - { - return $this->createNewResource(); - } - /** * {@inheritDoc} */ diff --git a/src/Components/rpc/src/Client/Pool/RpcClientCoroutinePool.php b/src/Components/rpc/src/Client/Pool/RpcClientCoroutinePool.php index 7cb8402fd6..3b87c4324f 100644 --- a/src/Components/rpc/src/Client/Pool/RpcClientCoroutinePool.php +++ b/src/Components/rpc/src/Client/Pool/RpcClientCoroutinePool.php @@ -27,14 +27,6 @@ public function __construct(string $name, \Imi\Pool\Interfaces\IPoolConfig $conf $this->initUriResourceConfig(); } - /** - * {@inheritDoc} - */ - protected function createResource(): IPoolResource - { - return $this->createNewResource(); - } - /** * {@inheritDoc} */ diff --git a/src/Components/rpc/src/Client/Pool/RpcClientSyncPool.php b/src/Components/rpc/src/Client/Pool/RpcClientSyncPool.php index b2f409f713..56215c714c 100644 --- a/src/Components/rpc/src/Client/Pool/RpcClientSyncPool.php +++ b/src/Components/rpc/src/Client/Pool/RpcClientSyncPool.php @@ -27,14 +27,6 @@ public function __construct(string $name, \Imi\Pool\Interfaces\IPoolConfig $conf $this->initUriResourceConfig(); } - /** - * {@inheritDoc} - */ - protected function createResource(): IPoolResource - { - return $this->createNewResource(); - } - /** * {@inheritDoc} */ diff --git a/src/Components/shared-memory/src/Pool/ClientPool.php b/src/Components/shared-memory/src/Pool/ClientPool.php index 87e768a074..ed4e9939b8 100644 --- a/src/Components/shared-memory/src/Pool/ClientPool.php +++ b/src/Components/shared-memory/src/Pool/ClientPool.php @@ -14,14 +14,6 @@ */ class ClientPool extends BaseAsyncPool { - /** - * {@inheritDoc} - */ - protected function createResource(): IPoolResource - { - return $this->createNewResource(); - } - /** * {@inheritDoc} */ diff --git a/src/Components/swoole/src/Db/Driver/Swoole/Driver.php b/src/Components/swoole/src/Db/Driver/Swoole/Driver.php deleted file mode 100644 index 4f5b2970a2..0000000000 --- a/src/Components/swoole/src/Db/Driver/Swoole/Driver.php +++ /dev/null @@ -1,418 +0,0 @@ - 'MySQL IP地址', - * 'username' => '数据用户', - * 'password' => '数据库密码', - * 'database' => '数据库名', - * 'port' => 'MySQL端口 默认3306 可选参数', - * 'timeout' => '建立连接超时时间', - * 'charset' => '字符集', - * 'strict_type'=> true, // 开启严格模式,query方法返回的数据也将转为强类型 - * 'fetch_mode' => false, // 开启fetch模式, 可与pdo一样使用fetch/fetchAll逐行或获取全部结果集(4.0版本以上) - * 'options' => [], // 其它选项 - * ]. - */ - public function __construct(array $option = []) - { - parent::__construct($option); - $this->isCacheStatement = Config::get('@app.db.statement.cache', true); - } - - /** - * {@inheritDoc} - */ - public function isConnected(): bool - { - return $this->instance && $this->instance->connected; - } - - /** - * {@inheritDoc} - */ - public function ping(): bool - { - $instance = $this->instance; - if (!$instance) - { - return false; - } - if ($instance->query('select 1')) - { - return true; - } - if ($this->checkCodeIsOffline($instance->errno)) - { - $this->close(); - } - - return false; - } - - /** - * {@inheritDoc} - */ - public function open(): bool - { - $this->instance = $instance = new MySQL(); - $option = $this->option; - $serverConfig = [ - 'host' => $option['host'] ?? '127.0.0.1', - 'port' => (int) ($option['port'] ?? 3306), - 'user' => $option['username'] ?? 'root', - 'password' => $option['password'] ?? '', - 'database' => $option['database'] ?? '', - 'timeout' => $option['timeout'] ?? null, - 'charset' => $option['charset'] ?? 'utf8', - 'strict_type' => $option['strict_type'] ?? true, - 'fetch_mode' => $option['fetch_mode'] ?? false, - ]; - if (isset($option['options'])) - { - $serverConfig = array_merge($serverConfig, $option['options']); - } - if ($instance->connect($serverConfig)) - { - $this->execInitSqls(); - - return true; - } - - return false; - } - - /** - * {@inheritDoc} - */ - public function close(): void - { - StatementManager::clear($this); - if (null !== $this->lastStmt) - { - $this->lastStmt = null; - } - if (null !== $this->instance) - { - $this->instance->close(); - $this->instance = null; - } - if ($this->transaction) - { - $this->transaction->init(); - } - } - - /** - * {@inheritDoc} - */ - public function getInstance(): MySQL - { - return $this->instance; - } - - /** - * {@inheritDoc} - */ - public function beginTransaction(): bool - { - if (!$this->inTransaction() && !$this->instance->begin()) - { - if ($this->checkCodeIsOffline($this->instance->errno)) - { - $this->close(); - } - - return false; - } - $this->exec('SAVEPOINT P' . $this->getTransactionLevels()); - $this->getTransaction()->beginTransaction(); - - return true; - } - - /** - * {@inheritDoc} - */ - public function commit(): bool - { - if (!$this->instance->commit()) - { - if ($this->checkCodeIsOffline($this->instance->errno)) - { - $this->close(); - } - - return false; - } - - return $this->getTransaction()->commit(); - } - - /** - * {@inheritDoc} - */ - public function rollBack(?int $levels = null): bool - { - if (null === $levels || ($toLevel = $this->getTransactionLevels() - $levels) <= 0) - { - $result = $this->instance->rollback(); - } - else - { - $this->exec('ROLLBACK TO P' . $toLevel); - $result = true; - } - if ($result) - { - $this->getTransaction()->rollBack($levels); - } - elseif ($this->checkCodeIsOffline($this->instance->errno)) - { - $this->close(); - } - - return $result; - } - - /** - * {@inheritDoc} - */ - public function getTransactionLevels(): int - { - return $this->getTransaction()->getTransactionLevels(); - } - - /** - * {@inheritDoc} - */ - public function inTransaction(): bool - { - return $this->getTransaction()->getTransactionLevels() > 0; - } - - /** - * {@inheritDoc} - */ - public function errorCode(): mixed - { - if ($this->lastStmt && $this->lastStmt instanceof \Swoole\Coroutine\MySQL\Statement) - { - return $this->lastStmt->errno; - } - elseif ($this->instance->connected) - { - return $this->instance->errno; - } - else - { - return $this->instance->connect_errno; - } - } - - /** - * {@inheritDoc} - */ - public function errorInfo(): string - { - if ($this->lastStmt && $this->lastStmt instanceof \Swoole\Coroutine\MySQL\Statement) - { - return $this->lastStmt->error; - } - elseif ($this->instance->connected) - { - return $this->instance->error; - } - else - { - return $this->instance->connect_error; - } - } - - /** - * {@inheritDoc} - */ - public function lastSql(): string - { - return $this->lastSql; - } - - /** - * {@inheritDoc} - */ - public function exec(string $sql): int - { - $this->lastStmt = null; - $this->lastSql = $sql; - $instance = $this->instance; - if (false === $instance->query($sql) && $this->checkCodeIsOffline($this->instance->errno)) - { - $this->close(); - - return 0; - } - - return $instance->affected_rows; - } - - /** - * {@inheritDoc} - */ - public function batchExec(string $sql): array - { - $result = []; - foreach (SqlUtil::parseMultiSql($sql) as $itemSql) - { - $queryResult = $this->query($itemSql); - $result[] = $queryResult->fetchAll(); - } - - return $result; - } - - /** - * {@inheritDoc} - */ - public function getAttribute(mixed $attribute): mixed - { - return null; - } - - /** - * {@inheritDoc} - */ - public function setAttribute(mixed $attribute, mixed $value): bool - { - return true; - } - - /** - * {@inheritDoc} - */ - public function lastInsertId(?string $name = null): string - { - return (string) $this->instance->insert_id; - } - - /** - * {@inheritDoc} - */ - public function rowCount(): int - { - return null === $this->lastStmt ? $this->instance->affected_rows : $this->lastStmt->affected_rows; - } - - /** - * {@inheritDoc} - */ - public function prepare(string $sql, array $driverOptions = []): IMysqlStatement - { - if ($this->isCacheStatement && $stmtCache = StatementManager::get($this, $sql)) - { - $stmt = $stmtCache['statement']; - } - else - { - $this->lastSql = $sql; - $parsedSql = SqlUtil::parseSqlWithColonParams($sql, $sqlParamsMap); - $lastStmt = $this->instance->prepare($parsedSql); - if (false === $lastStmt) - { - $errorCode = $this->errorCode(); - $errorInfo = $this->errorInfo(); - if ($this->checkCodeIsOffline($errorCode)) - { - $this->close(); - } - throw new DbException('SQL prepare error [' . $errorCode . '] ' . $errorInfo . \PHP_EOL . 'sql: ' . $sql . \PHP_EOL); - } - $this->lastStmt = $lastStmt; - $stmt = BeanFactory::newInstance(Statement::class, $this, $lastStmt, $sql, $sqlParamsMap); - if ($this->isCacheStatement && !isset($stmtCache)) - { - StatementManager::setNX($stmt, true); - } - } - - return $stmt; - } - - /** - * {@inheritDoc} - */ - public function query(string $sql): IMysqlStatement - { - $this->lastSql = $sql; - $lastStmt = $this->instance->query($sql); - if (false === $lastStmt) - { - $errorCode = $this->errorCode(); - $errorInfo = $this->errorInfo(); - if ($this->checkCodeIsOffline($errorCode)) - { - $this->close(); - } - throw new DbException('SQL query error: [' . $errorCode . '] ' . $errorInfo . \PHP_EOL . 'sql: ' . $sql . \PHP_EOL); - } - $this->lastStmt = $lastStmt; - - return BeanFactory::newInstance(Statement::class, $this, $lastStmt, $sql); - } - - /** - * {@inheritDoc} - */ - public function getTransaction(): Transaction - { - return $this->transaction ??= new Transaction(); - } -} diff --git a/src/Components/swoole/src/Db/Driver/Swoole/Statement.php b/src/Components/swoole/src/Db/Driver/Swoole/Statement.php deleted file mode 100644 index 20a4b342b3..0000000000 --- a/src/Components/swoole/src/Db/Driver/Swoole/Statement.php +++ /dev/null @@ -1,388 +0,0 @@ -result = $statement; - } - } - - /** - * {@inheritDoc} - */ - public function getDb(): IMysqlDb - { - return $this->db; - } - - /** - * {@inheritDoc} - */ - public function bindColumn(string|int $column, mixed &$var, int $type = \PDO::PARAM_STR, int $maxLength = 0, mixed $driverOptions = null): bool - { - $this->bindValues[$column] = $var; - - return true; - } - - /** - * {@inheritDoc} - */ - public function bindParam(string|int $param, mixed &$var, int $type = \PDO::PARAM_STR, int $maxLength = 0, mixed $driverOptions = null): bool - { - $this->bindValues[$param] = $var; - - return true; - } - - /** - * {@inheritDoc} - */ - public function bindValue(string|int $param, mixed $value, int $type = \PDO::PARAM_STR): bool - { - $this->bindValues[$param] = $value; - - return true; - } - - /** - * {@inheritDoc} - */ - public function closeCursor(): bool - { - return true; - } - - /** - * {@inheritDoc} - */ - public function columnCount(): int - { - return \count($this->result[0] ?? []); - } - - /** - * {@inheritDoc} - */ - public function errorCode(): mixed - { - return \is_array($this->statement) ? $this->db->errorCode() : $this->statement->errno; - } - - /** - * {@inheritDoc} - */ - public function errorInfo(): string - { - return \is_array($this->statement) ? $this->db->errorInfo() : $this->statement->error; - } - - /** - * {@inheritDoc} - */ - public function getSql(): string - { - return $this->lastSql; - } - - /** - * {@inheritDoc} - */ - public function execute(array $inputParameters = null): bool - { - $statement = $this->statement; - if (\is_array($statement)) - { - $result = $this->db->getInstance()->query($this->lastSql); - if (false === $result) - { - $db = $this->db; - $dbInstance = $db->getInstance(); - $errorCode = $dbInstance->errorCode(); - $errorInfo = $dbInstance->errorInfo(); - if ($db->checkCodeIsOffline($errorCode)) - { - $db->close(); - } - throw new DbException('SQL query error: [' . $errorCode . '] ' . $errorInfo . \PHP_EOL . 'sql: ' . $this->getSql() . \PHP_EOL); - } - } - else - { - if (null === $inputParameters) - { - $inputParameters = $this->bindValues; - } - $this->bindValues = $bindValues = []; - if ($inputParameters) - { - $sqlParamsMap = $this->sqlParamsMap; - if ($sqlParamsMap) - { - foreach ($sqlParamsMap as $index => $paramName) - { - if (isset($inputParameters[$paramName])) - { - $bindValues[$index] = $inputParameters[$paramName]; - } - elseif (isset($inputParameters[$key = ':' . $paramName])) - { - $bindValues[$index] = $inputParameters[$key]; - } - else - { - // for inputParameters paramName : null - $bindValues[$index] = null; - } - } - } - else - { - foreach ($inputParameters as $k => $v) - { - $bindValues[$k] = $v; - } - } - } - if ($bindValues) - { - ksort($bindValues); - $bindValues = array_values($bindValues); - } - $result = $statement->execute($bindValues); - if (true === $result) - { - $result = $statement->fetchAll(); - if (false === $result) - { - $result = []; - } - } - elseif (false === $result) - { - $errorCode = $this->errorCode(); - $errorInfo = $this->errorInfo(); - if ($this->db->checkCodeIsOffline($errorCode)) - { - $this->db->close(); - } - throw new DbException('SQL query error: [' . $errorCode . '] ' . $errorInfo . \PHP_EOL . 'sql: ' . $this->getSql() . \PHP_EOL); - } - } - $this->result = (true === $result ? [] : $result); - - return true; - } - - /** - * {@inheritDoc} - */ - public function fetch(int $fetchStyle = \PDO::FETCH_ASSOC, int $cursorOrientation = \PDO::FETCH_ORI_NEXT, int $cursorOffset = 0): mixed - { - $result = current($this->result); - if ($result) - { - next($this->result); - } - - return $result; - } - - /** - * {@inheritDoc} - */ - public function fetchAll(int $fetchStyle = \PDO::FETCH_ASSOC, mixed $fetchArgument = null, array $ctorArgs = []): array - { - return $this->result; - } - - /** - * {@inheritDoc} - */ - public function fetchColumn(int $column = 0): mixed - { - $row = current($this->result); - if ($row) - { - next($this->result); - if (isset($row[$column])) - { - return $row[$column]; - } - elseif (is_numeric($column)) - { - return array_values($row)[$column] ?? null; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function fetchObject(string $className = \stdClass::class, ?array $ctorArgs = null): mixed - { - $row = current($this->result); - if (false === $row) - { - return null; - } - next($this->result); - if (\stdClass::class === $className) - { - return (object) $row; - } - $result = new $className(); - foreach ($row as $k => $v) - { - $result->{$k} = $v; - } - - return $result; - } - - /** - * {@inheritDoc} - */ - public function getAttribute(mixed $attribute): mixed - { - return null; - } - - /** - * {@inheritDoc} - */ - public function setAttribute(mixed $attribute, mixed $value): bool - { - return true; - } - - /** - * {@inheritDoc} - */ - public function nextRowset(): bool - { - if ($this->statement instanceof \Swoole\Coroutine\MySQL\Statement) - { - $result = $this->statement->nextResult(); - if ($result) - { - $result = $this->statement->fetchAll(); - if (false === $result) - { - $result = []; - } - $this->result = $result; - - return true; - } - } - - return false; - } - - /** - * {@inheritDoc} - */ - public function lastInsertId(?string $name = null): string - { - return \is_array($this->statement) ? $this->db->lastInsertId() : (string) $this->statement->insert_id; - } - - /** - * {@inheritDoc} - */ - public function rowCount(): int - { - return \is_array($this->statement) ? $this->db->rowCount() : $this->statement->affected_rows; - } - - /** - * {@inheritDoc} - */ - public function getInstance(): object - { - return $this->statement; - } - - public function current(): mixed - { - return current($this->result); - } - - public function key(): int|string|null - { - return key($this->result); - } - - /** - * {@inheritDoc} - */ - public function next(): void - { - next($this->result); - } - - /** - * {@inheritDoc} - */ - public function rewind(): void - { - reset($this->result); - } - - /** - * {@inheritDoc} - */ - public function valid(): bool - { - return false !== $this->current(); - } -} diff --git a/src/Components/swoole/src/Db/Pool/CoroutineDbPool.php b/src/Components/swoole/src/Db/Pool/CoroutineDbPool.php index adf432d079..191b0f61d8 100644 --- a/src/Components/swoole/src/Db/Pool/CoroutineDbPool.php +++ b/src/Components/swoole/src/Db/Pool/CoroutineDbPool.php @@ -23,14 +23,6 @@ public function __construct(string $name, \Imi\Pool\Interfaces\IPoolConfig $conf $this->initUriResourceConfig(); } - /** - * {@inheritDoc} - */ - protected function createResource(): IPoolResource - { - return $this->createNewResource(); - } - /** * {@inheritDoc} */ diff --git a/src/Components/swoole/tests/phpunit.xml b/src/Components/swoole/tests/phpunit.xml index 0ae52b5317..393a1329cb 100644 --- a/src/Components/swoole/tests/phpunit.xml +++ b/src/Components/swoole/tests/phpunit.xml @@ -29,9 +29,6 @@ unit/UDPServer/Tests - - unit/Component/Performance - diff --git a/src/Components/swoole/tests/unit/Component/Performance/SwooleMysqlDbTest.php b/src/Components/swoole/tests/unit/Component/Performance/SwooleMysqlDbTest.php deleted file mode 100644 index 39146045af..0000000000 --- a/src/Components/swoole/tests/unit/Component/Performance/SwooleMysqlDbTest.php +++ /dev/null @@ -1,18 +0,0 @@ - [ - 'pool' => [ - // 协程池类名 - 'class' => \Imi\Swoole\Db\Pool\CoroutineDbPool::class, - // 连接池配置 - 'config' => [ - 'maxResources' => 10, - 'minResources' => 1, - 'checkStateWhenGetResource' => false, - ], - ], - // 连接池资源配置 - 'resource' => [ - 'host' => env('MYSQL_SERVER_HOST', '127.0.0.1'), - 'port' => env('MYSQL_SERVER_PORT', 3306), - 'username' => env('MYSQL_SERVER_USERNAME', 'root'), - 'password' => env('MYSQL_SERVER_PASSWORD', 'root'), - 'database' => 'db_imi_test', - 'charset' => 'utf8mb4', - 'dbClass' => \Imi\Swoole\Db\Driver\Swoole\Driver::class, - ], - ], // mysqli 'mysqli' => [ 'pool' => [ diff --git a/src/Components/swoole/tests/unit/HttpServer/ApiServer/Controller/IndexController.php b/src/Components/swoole/tests/unit/HttpServer/ApiServer/Controller/IndexController.php index 127d847652..f5c63fc528 100644 --- a/src/Components/swoole/tests/unit/HttpServer/ApiServer/Controller/IndexController.php +++ b/src/Components/swoole/tests/unit/HttpServer/ApiServer/Controller/IndexController.php @@ -7,7 +7,6 @@ use Imi\Aop\Annotation\Inject; use Imi\HttpValidate\Annotation\HttpValidation; use Imi\RequestContext; -use Imi\Server\Http\Annotation\ExtractData; use Imi\Server\Http\Annotation\RequestParam; use Imi\Server\Http\Controller\HttpController; use Imi\Server\Http\Message\Emitter\SseEmitter; @@ -316,18 +315,6 @@ public function type(int $id, string $name, int $page): array return compact('id', 'name', 'page'); } - #[Action] - #[ExtractData(name: '$get.id', to: 'id2')] - #[ExtractData(name: '$get.id', to: 'id3')] - public function extractData(int $id, int $id2, string $id3): array - { - return [ - 'id' => $id, - 'id2' => $id2, - 'id3' => $id3, - ]; - } - #[Action] #[RequestParam(name: '$get.id', param: 'id2')] #[RequestParam(name: '$get.id3', param: 'id3', required: false, default: 'imi 666')] diff --git a/src/Components/swoole/tests/unit/HttpServer/Tests/RequestTest.php b/src/Components/swoole/tests/unit/HttpServer/Tests/RequestTest.php index 562cd8140e..bbb0e27fab 100644 --- a/src/Components/swoole/tests/unit/HttpServer/Tests/RequestTest.php +++ b/src/Components/swoole/tests/unit/HttpServer/Tests/RequestTest.php @@ -305,20 +305,6 @@ public function testMoreUrlParams(): void ]), $response->body()); } - /** - * Annotation ExtractData. - */ - public function testExtractData(): void - { - $http = new HttpRequest(); - $response = $http->get($this->host . 'extractData?id=123'); - $this->assertEquals(json_encode([ - 'id' => 123, - 'id2' => 123, - 'id3' => '123', - ]), $response->body()); - } - /** * Annotation RequestParam. */ diff --git a/src/Db/Pool/SyncDbPool.php b/src/Db/Pool/SyncDbPool.php index 8b6ff80466..c9821af782 100644 --- a/src/Db/Pool/SyncDbPool.php +++ b/src/Db/Pool/SyncDbPool.php @@ -22,14 +22,6 @@ public function __construct(string $name, \Imi\Pool\Interfaces\IPoolConfig $conf $this->initUriResourceConfig(); } - /** - * {@inheritDoc} - */ - protected function createResource(): IPoolResource - { - return $this->createNewResource(); - } - /** * {@inheritDoc} */ diff --git a/src/Db/Query/Interfaces/IQuery.php b/src/Db/Query/Interfaces/IQuery.php index effeac7eaf..b5d1235bc4 100644 --- a/src/Db/Query/Interfaces/IQuery.php +++ b/src/Db/Query/Interfaces/IQuery.php @@ -314,13 +314,6 @@ public function chunkById(int $count, string $column, ?string $alias = null, str */ public function chunkByOffset(int $count): ChunkByOffsetResult; - /** - * 查询所有记录,返回分块迭代器. - * - * @deprecated 3.0 - */ - public function chunkEach(int $count, string $column, ?string $alias = null): mixed; - /** * 分页查询. */ @@ -460,15 +453,6 @@ public function setFieldDec(string $fieldName, float $decValue = 1): self; */ public function getAutoParamName(string $prefix = ':p'): string; - /** - * 查询器别名. - * - * @deprecated 3.0 - * - * @return static - */ - public function alias(string $name, ?callable $callable = null): self; - /** * 加锁 * diff --git a/src/Db/Query/Query.php b/src/Db/Query/Query.php index 96ffc38b7a..0d364da782 100644 --- a/src/Db/Query/Query.php +++ b/src/Db/Query/Query.php @@ -76,18 +76,6 @@ abstract class Query implements IQuery protected string $originPrefix = ''; - /** - * 查询器别名集合. - * - * @var static[] - */ - protected static array $aliasMap = []; - - /** - * 当前别名. - */ - protected ?string $alias = null; - /** * 查询结果集类名. * @@ -95,11 +83,6 @@ abstract class Query implements IQuery */ protected string $resultClass = Result::class; - /** - * 别名 Sql 数据集合. - */ - protected static array $aliasSqlMap = []; - /** * 构建 Sql 前的回调. * @@ -811,25 +794,6 @@ protected function isInTransaction(): bool return $this->getDb()->inTransaction(); } - /** - * {@inheritDoc} - */ - public function alias(string $name, ?callable $callable = null): self - { - $aliasMap = &static::$aliasMap; - if (!isset($aliasMap[$name])) - { - if ($callable) - { - $callable($this); - } - $this->alias = $name; - $aliasMap[$name] = $this; - } - - return clone $aliasMap[$name]; - } - /** * {@inheritDoc} */ @@ -873,53 +837,8 @@ public function buildSelectSql(): string $this->beforeBuildSqlCallbacks = []; } - $alias = $this->alias; - $aliasSqlMap = &static::$aliasSqlMap; - if ($alias && isset($aliasSqlMap[$alias])) - { - $aliasSqlData = $aliasSqlMap[$alias]; - $sql = $aliasSqlData['sql']; - $binds = $aliasSqlData['binds']; - if ($binds) - { - if ($this->binds) - { - $this->binds = array_merge($binds, $this->binds); - } - else - { - $this->binds = $binds; - } - } - } - else - { - if ($alias) - { - $binds = $this->binds; - $this->binds = []; - } - $builderClass = static::SELECT_BUILDER_CLASS; - $sql = (new $builderClass($this))->build(); - if ($alias) - { - $originBinds = $binds; - $binds = $this->binds; - // @phpstan-ignore-next-line todo 此处 $binds 为无效判断,已经利用 $alias 在前一个 if 中置空了。 - if ($binds) - { - $this->binds = array_merge($originBinds, $binds); - } - else - { - $this->binds = $originBinds; - } - $aliasSqlMap[$alias] = [ - 'sql' => $sql, - 'binds' => $binds, - ]; - } - } + $builderClass = static::SELECT_BUILDER_CLASS; + $sql = (new $builderClass($this))->build(); if (!$this->isInitQueryType && !$this->isInTransaction()) { $this->queryType = QueryType::READ; @@ -942,57 +861,8 @@ public function buildInsertSql(array|object|null $data = null): string } $this->beforeBuildSqlCallbacks = []; } - $alias = $this->alias; - $aliasSqlMap = &static::$aliasSqlMap; - if ($alias && isset($aliasSqlMap[$alias])) - { - $aliasSqlData = $aliasSqlMap[$alias]; - $sql = $aliasSqlData['sql']; - $binds = $aliasSqlData['binds']; - if ($binds) - { - if ($this->binds) - { - $this->binds = array_merge($binds, $this->binds); - } - else - { - $this->binds = $binds; - } - } - $bindValues = []; - $numberKey = isset($data[0]); - foreach ($data as $k => $v) - { - if ($numberKey) - { - $bindValues[':' . ($k + 1)] = $v; - } - else - { - $bindValues[':' . $k] = $v; - } - } - $this->bindValues($bindValues); - } - else - { - if ($alias) - { - $binds = $this->binds; - $this->binds = []; - } - $builderClass = static::INSERT_BUILDER_CLASS; - $sql = (new $builderClass($this))->build($data); - if ($alias) - { - $aliasSqlMap[$alias] = [ - 'sql' => $sql, - // @phpstan-ignore-next-line - 'binds' => $binds, - ]; - } - } + $builderClass = static::INSERT_BUILDER_CLASS; + $sql = (new $builderClass($this))->build($data); return $sql; } @@ -1030,59 +900,8 @@ public function buildUpdateSql(array|object|null $data = null): string } $this->beforeBuildSqlCallbacks = []; } - $alias = $this->alias; - $aliasSqlMap = &static::$aliasSqlMap; - if ($alias && isset($aliasSqlMap[$alias])) - { - $aliasSqlData = $aliasSqlMap[$alias]; - $sql = $aliasSqlData['sql']; - $binds = $aliasSqlData['binds']; - if ($binds) - { - if ($this->binds) - { - $this->binds = array_merge($binds, $this->binds); - } - else - { - $this->binds = $binds; - } - } - $bindValues = []; - foreach ($data as $k => $v) - { - $bindValues[':' . $k] = $v; - } - $this->bindValues($bindValues); - } - else - { - if ($alias) - { - $binds = $this->binds; - $this->binds = []; - } - $builderClass = static::UPDATE_BUILDER_CLASS; - $sql = (new $builderClass($this))->build($data); - if ($alias) - { - // @phpstan-ignore-next-line - $originBinds = $binds; - $binds = $this->binds; - if ($binds) - { - $this->binds = array_merge($originBinds, $binds); - } - else - { - $this->binds = $originBinds; - } - $aliasSqlMap[$alias] = [ - 'sql' => $sql, - 'binds' => $binds, - ]; - } - } + $builderClass = static::UPDATE_BUILDER_CLASS; + $sql = (new $builderClass($this))->build($data); return $sql; } @@ -1101,59 +920,8 @@ public function buildReplaceSql(array|object|null $data = null, array $uniqueFie } $this->beforeBuildSqlCallbacks = []; } - $alias = $this->alias; - $aliasSqlMap = &static::$aliasSqlMap; - if ($alias && isset($aliasSqlMap[$alias])) - { - $aliasSqlData = $aliasSqlMap[$alias]; - $sql = $aliasSqlData['sql']; - $binds = $aliasSqlData['binds']; - if ($binds) - { - if ($this->binds) - { - $this->binds = array_merge($binds, $this->binds); - } - else - { - $this->binds = $binds; - } - } - $bindValues = []; - foreach ($data as $k => $v) - { - $bindValues[':' . $k] = $v; - } - $this->bindValues($bindValues); - } - else - { - if ($alias) - { - $binds = $this->binds; - $this->binds = []; - } - $builderClass = static::REPLACE_BUILDER_CLASS; - $sql = (new $builderClass($this))->build($data, $uniqueFields); - if ($alias) - { - // @phpstan-ignore-next-line - $originBinds = $binds; - $binds = $this->binds; - if ($binds) - { - $this->binds = array_merge($originBinds, $binds); - } - else - { - $this->binds = $originBinds; - } - $aliasSqlMap[$alias] = [ - 'sql' => $sql, - 'binds' => $binds, - ]; - } - } + $builderClass = static::REPLACE_BUILDER_CLASS; + $sql = (new $builderClass($this))->build($data, $uniqueFields); return $sql; } @@ -1172,53 +940,8 @@ public function buildDeleteSql(): string } $this->beforeBuildSqlCallbacks = []; } - $alias = $this->alias; - $aliasSqlMap = &static::$aliasSqlMap; - if ($alias && isset($aliasSqlMap[$alias])) - { - $aliasSqlData = $aliasSqlMap[$alias]; - $sql = $aliasSqlData['sql']; - $binds = $aliasSqlData['binds']; - if ($binds) - { - if ($this->binds) - { - $this->binds = array_merge($binds, $this->binds); - } - else - { - $this->binds = $binds; - } - } - } - else - { - if ($alias) - { - $binds = $this->binds; - $this->binds = []; - } - $builderClass = static::DELETE_BUILDER_CLASS; - $sql = (new $builderClass($this))->build(); - if ($alias) - { - // @phpstan-ignore-next-line - $originBinds = $binds; - $binds = $this->binds; - if ($binds) - { - $this->binds = array_merge($originBinds, $binds); - } - else - { - $this->binds = $originBinds; - } - $aliasSqlMap[$alias] = [ - 'sql' => $sql, - 'binds' => $binds, - ]; - } - } + $builderClass = static::DELETE_BUILDER_CLASS; + $sql = (new $builderClass($this))->build(); return $sql; } @@ -1315,14 +1038,6 @@ public function chunkByOffset(int $count): ChunkByOffsetResult return new ChunkByOffsetResult($this, $count); } - /** - * 查询所有记录,返回分块迭代器. - */ - public function chunkEach(int $count, string $column, ?string $alias = null): mixed - { - return $this->chunkById($count, $column, $alias)->each(); - } - /** * {@inheritDoc} */ diff --git a/src/HttpValidate/Annotation/ExtractData.php b/src/HttpValidate/Annotation/ExtractData.php deleted file mode 100644 index 9dbc61ebe9..0000000000 --- a/src/HttpValidate/Annotation/ExtractData.php +++ /dev/null @@ -1,15 +0,0 @@ -onError(...), $this->catchLevel); - set_exception_handler($this->onException(...)); + set_exception_handler(static fn (\Throwable $th) => Log::error($th)); } /** @@ -83,14 +83,4 @@ public function onShutdown(): void echo $th->getMessage(), ' ', $th->getFile(), ':', $th->getLine(), \PHP_EOL; } } - - /** - * 致命错误. - * - * @deprecated 3.0 - */ - public function onException(\Throwable $th): void - { - Log::error($th); - } } diff --git a/src/Model/Annotation/DDL.php b/src/Model/Annotation/DDL.php index 642f7a0904..87cadbc37e 100644 --- a/src/Model/Annotation/DDL.php +++ b/src/Model/Annotation/DDL.php @@ -12,9 +12,6 @@ #[\Attribute(\Attribute::TARGET_CLASS)] class DDL extends Base { - /** - * @todo $decode 类型改为:?callable - */ public function __construct( /** * 表结构 SQL;CREATE TABLE 语句. diff --git a/src/Model/Traits/TJsonValue.php b/src/Model/Traits/TJsonValue.php index 1a9817497e..09c9b89f5c 100644 --- a/src/Model/Traits/TJsonValue.php +++ b/src/Model/Traits/TJsonValue.php @@ -10,20 +10,17 @@ trait TJsonValue { - /** - * @param mixed $value - */ - protected static function parseJsonInitValue(string $name, $value, Column $fieldAnnotation, Meta $meta): mixed + protected static function parseJsonInitValue(string $name, mixed $value, Column $fieldAnnotation, Meta $meta): mixed { $fieldsJsonDecode = $meta->getFieldsJsonDecode(); $realJsonDecode = $fieldsJsonDecode[$name][0] ?? $meta->getJsonDecode(); if ($realJsonDecode) { - $data = json_decode($value, $realJsonDecode->associative, $realJsonDecode->depth, $realJsonDecode->flags); + $data = json_decode((string) $value, $realJsonDecode->associative, $realJsonDecode->depth, $realJsonDecode->flags); } else { - $data = json_decode($value, true); + $data = json_decode((string) $value, true); } if (\JSON_ERROR_NONE === json_last_error()) { @@ -79,10 +76,7 @@ protected static function parseJsonInitValue(string $name, $value, Column $field return $value; } - /** - * @param mixed $value - */ - protected static function parseJsonSaveValue(string $name, $value, Column $fieldAnnotation, Meta $meta): mixed + protected static function parseJsonSaveValue(string $name, mixed $value, Column $fieldAnnotation, Meta $meta): mixed { $fieldsJsonEncode = $meta->getFieldsJsonEncode(); if (isset($fieldsJsonEncode[$name][0])) diff --git a/src/Model/Traits/TListValue.php b/src/Model/Traits/TListValue.php index 6896668ea8..c7d54227e2 100644 --- a/src/Model/Traits/TListValue.php +++ b/src/Model/Traits/TListValue.php @@ -9,10 +9,7 @@ trait TListValue { - /** - * @param mixed $value - */ - protected static function parseListInitValue(string $name, $value, Column $fieldAnnotation, Meta $meta): mixed + protected static function parseListInitValue(string $name, mixed $value, Column $fieldAnnotation, Meta $meta): mixed { if ('' === $value) { @@ -20,16 +17,13 @@ protected static function parseListInitValue(string $name, $value, Column $field } elseif (null !== $fieldAnnotation->listSeparator) { - return '' === $fieldAnnotation->listSeparator ? [] : explode($fieldAnnotation->listSeparator, $value); + return '' === $fieldAnnotation->listSeparator ? [] : explode($fieldAnnotation->listSeparator, (string) $value); } return $value; } - /** - * @param mixed $value - */ - protected static function parseListSaveValue(string $name, $value, Column $fieldAnnotation, Meta $meta): mixed + protected static function parseListSaveValue(string $name, mixed $value, Column $fieldAnnotation, Meta $meta): mixed { if (null !== $value && null !== $fieldAnnotation->listSeparator) { diff --git a/src/Model/Traits/TModelQuery.php b/src/Model/Traits/TModelQuery.php index 17df3d7c6b..d8431bf188 100644 --- a/src/Model/Traits/TModelQuery.php +++ b/src/Model/Traits/TModelQuery.php @@ -115,16 +115,6 @@ public function chunkByOffset(int $count): ChunkByOffsetResult return parent::chunkByOffset($count); } - /** - * {@inheritDoc} - */ - public function chunkEach(int $count, string $column, ?string $alias = null): mixed - { - $this->queryPreProcess(); - - return parent::chunkEach($count, $column, $alias); - } - /** * 执行SQL语句. */ diff --git a/src/Model/Traits/TSetValue.php b/src/Model/Traits/TSetValue.php index 292593fba7..4a63aa03f7 100644 --- a/src/Model/Traits/TSetValue.php +++ b/src/Model/Traits/TSetValue.php @@ -9,10 +9,7 @@ trait TSetValue { - /** - * @param mixed $value - */ - protected static function parseSetInitValue(string $name, $value, Column $fieldAnnotation, Meta $meta): mixed + protected static function parseSetInitValue(string $name, mixed $value, Column $fieldAnnotation, Meta $meta): mixed { if ('' === $value) { @@ -20,14 +17,11 @@ protected static function parseSetInitValue(string $name, $value, Column $fieldA } else { - return explode(',', $value); + return explode(',', (string) $value); } } - /** - * @param mixed $value - */ - protected static function parseSetSaveValue(string $name, $value, Column $fieldAnnotation, Meta $meta): mixed + protected static function parseSetSaveValue(string $name, mixed $value, Column $fieldAnnotation, Meta $meta): mixed { return implode(',', $value); } diff --git a/src/Pool/BasePool.php b/src/Pool/BasePool.php index d60f603f96..33e8805735 100644 --- a/src/Pool/BasePool.php +++ b/src/Pool/BasePool.php @@ -261,13 +261,6 @@ abstract protected function initQueue(): void; */ abstract protected function buildQueue(): void; - /** - * 创建资源. - * - * @deprecated 3.0 建议使用 createNewResource() - */ - abstract protected function createResource(): IPoolResource; - /** * 把资源加入队列. */ @@ -276,10 +269,7 @@ abstract protected function push(IPoolResource $resource): void; /** * {@inheritDoc} */ - public function createNewResource(): IPoolResource - { - return $this->createResource(); - } + abstract public function createNewResource(): IPoolResource; /** * {@inheritDoc} diff --git a/src/Pool/ResourceConfigMode.php b/src/Pool/ResourceConfigMode.php index 786b727c22..609b559373 100644 --- a/src/Pool/ResourceConfigMode.php +++ b/src/Pool/ResourceConfigMode.php @@ -8,13 +8,6 @@ class ResourceConfigMode { use \Imi\Util\Traits\TStaticClass; - /** - * 轮询. - * - * @deprecated 3.0 请使用 ResourceConfigMode::ROUND_ROBIN - */ - public const TURN = 1; - /** * 轮询. */ diff --git a/src/Redis/Traits/TRedisPool.php b/src/Redis/Traits/TRedisPool.php index 902fc4b25b..8bb886ec73 100644 --- a/src/Redis/Traits/TRedisPool.php +++ b/src/Redis/Traits/TRedisPool.php @@ -16,7 +16,7 @@ trait TRedisPool * * @return \Imi\Redis\RedisResource */ - protected function createResource(): \Imi\Pool\Interfaces\IPoolResource + public function createNewResource(): \Imi\Pool\Interfaces\IPoolResource { $config = $this->getNextResourceConfig(); $mode = $config['mode'] ?? RedisMode::STANDALONE; diff --git a/src/Server/Http/Annotation/ExtractData.php b/src/Server/Http/Annotation/ExtractData.php deleted file mode 100644 index 07da46de5e..0000000000 --- a/src/Server/Http/Annotation/ExtractData.php +++ /dev/null @@ -1,32 +0,0 @@ -to] = [ - 'name' => $item->name, - 'default' => $item->default, - 'required' => false, - ]; - } - } if ($annotations[RequestParam::class]) { /** @var RequestParam $item */ diff --git a/src/Util/ArrayData.php b/src/Util/ArrayData.php index d7516c3dc1..ae74e0822e 100644 --- a/src/Util/ArrayData.php +++ b/src/Util/ArrayData.php @@ -83,14 +83,6 @@ public function &get(string|int|array|null $name = null, mixed $default = false) if (\is_string($name)) { $name = explode('.', $name); - // TODO: 3.0 去除判断 - // @phpstan-ignore-next-line - if (false === $name) - { - // @codeCoverageIgnoreStart - return $default; - // @codeCoverageIgnoreEnd - } } elseif (!\is_array($name)) { diff --git a/src/Util/DateTime.php b/src/Util/DateTime.php index ae53c771ea..b616b5d080 100644 --- a/src/Util/DateTime.php +++ b/src/Util/DateTime.php @@ -110,22 +110,6 @@ public static function getPrevWeek(?int $weekNo = null, ?string $format = null, return date($format, $timestamp); } - /** - * 获取上周的时间. - * - * 可传入 $weekNo 指定周几,周一到周日为1-7,不传则取时间戳对应周几 - * 可传入 $format 格式化,不传则返回时间戳 - * 可传入 $timestamp 指定时间戳,不传则取当前时间 - * - * @deprecated 3.0 错误的方法命名,请使用 getPrevWeek() - * - * @codeCoverageIgnore - */ - public static function getLastWeek(?int $weekNo = null, ?string $format = null, ?int $timestamp = null): string|int - { - return static::getPrevWeek($weekNo, $format, $timestamp); - } - /** * 获取一个月中的第几周. * diff --git a/src/functions.php b/src/functions.php index 38481e9141..17bd8fc4f0 100644 --- a/src/functions.php +++ b/src/functions.php @@ -4,7 +4,6 @@ namespace { - use Imi\Env; use Imi\RequestContext; use Imi\Swoole\Util\Coroutine; @@ -65,16 +64,6 @@ function imiCallable(callable $callable, bool $withGo = false): callable return $resultCallable; } } - - /** - * 获取环境变量值 - * - * @deprecated 3.0 - */ - function imiGetEnv(?string $varname = null, mixed $default = null): mixed - { - return Env::get($varname, $default); - } } namespace Imi diff --git a/tests/unit/Component/Tests/EnvTest.php b/tests/unit/Component/Tests/EnvTest.php index 286c670fd5..c86e794151 100644 --- a/tests/unit/Component/Tests/EnvTest.php +++ b/tests/unit/Component/Tests/EnvTest.php @@ -11,23 +11,6 @@ class EnvTest extends BaseTest { - public function testFunctionImiGetEnv(): void - { - $this->assertEquals(123, imiGetEnv('A')); - $this->assertEquals('imi', imiGetEnv('E')); - $this->assertEquals('123', imiGetEnv('A', 'default')); - $this->assertEquals(123, imiGetEnv('A', 0)); - $this->assertEquals(123.0, imiGetEnv('A', 3.14)); - $this->assertEquals('123', imiGetEnv('A', false)); - $this->assertFalse(imiGetEnv('B', false)); - $this->assertTrue(imiGetEnv('BOOL_TRUE', false)); - $this->assertFalse(imiGetEnv('BOOL_FALSE', false)); - $this->assertEquals(['1', '2', '3'], imiGetEnv('C', [])); - $this->assertEquals(['4', '5', '6'], imiGetEnv('D', [])); - $this->assertNull(imiGetEnv('NULL_VALUE')); - $this->assertNull(imiGetEnv('NULL_VALUE', 666)); - } - public function testFunctionEnv(): void { $this->assertEquals(123, env('A')); From 1c5ca1a9bd52e0ec65fbbfa5fe60e729b3a14226 Mon Sep 17 00:00:00 2001 From: zxin <14545600+NHZEX@users.noreply.github.com> Date: Tue, 14 Nov 2023 10:52:56 +0800 Subject: [PATCH 3/9] =?UTF-8?q?Update:=20=E4=BC=98=E5=8C=96=20ArrayUtil::i?= =?UTF-8?q?sAssoc=20(#645)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Util/ArrayUtil.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Util/ArrayUtil.php b/src/Util/ArrayUtil.php index 36102cb0a1..dcdfc4ab7b 100644 --- a/src/Util/ArrayUtil.php +++ b/src/Util/ArrayUtil.php @@ -107,7 +107,7 @@ public static function columnToKey(array $array, $column, bool $keepOld = true): */ public static function isAssoc(array $array): bool { - return array_keys($array) !== range(0, \count($array) - 1); + return !array_is_list($array); } /** From 2cb0bae095f38391dee5215b285d672b91845721 Mon Sep 17 00:00:00 2001 From: Yurun Date: Tue, 14 Nov 2023 11:07:58 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20rector?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dev/bootstrap.php | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/bootstrap.php b/dev/bootstrap.php index 4ae8684600..2d73dc4268 100644 --- a/dev/bootstrap.php +++ b/dev/bootstrap.php @@ -53,7 +53,6 @@ function getRectorConfigCallback(string $path): callable \Rector\Php71\Rector\FuncCall\CountOnNullRector::class, \Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector::class, \Rector\Php74\Rector\LNumber\AddLiteralSeparatorToNumberRector::class, - \Rector\Php74\Rector\FuncCall\ArraySpreadInsteadOfArrayMergeRector::class, // 性能很差 \Rector\CodeQuality\Rector\ClassMethod\OptionalParametersAfterRequiredRector::class, // 调整包含默认值的参数顺序,会导致代码被破坏 \Rector\Php81\Rector\ClassConst\FinalizePublicClassConstantRector::class, // 常量自动加 final,无法继承覆盖了 ]); From c1b25183a7abcfa65c275a186803dbd46e7befcd Mon Sep 17 00:00:00 2001 From: zxin <14545600+NHZEX@users.noreply.github.com> Date: Tue, 14 Nov 2023 15:11:31 +0800 Subject: [PATCH 5/9] =?UTF-8?q?Update:=20=E4=BC=98=E5=8C=96=E6=AF=8F?= =?UTF-8?q?=E6=97=A5=E6=B5=8B=E8=AF=95=20(#647)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/docker-compose.yml | 2 +- .github/workflows/daily-test.yml | 113 ++++++++++++++++++++++++++++--- 2 files changed, 106 insertions(+), 9 deletions(-) diff --git a/.github/docker-compose.yml b/.github/docker-compose.yml index 4279f63355..3890391a9d 100644 --- a/.github/docker-compose.yml +++ b/.github/docker-compose.yml @@ -140,7 +140,7 @@ services: POSTGRESQL_VERSION: ${POSTGRESQL_VERSION} volumes: - "${GITHUB_WORKSPACE}:/imi:rw" - - "/tmp/composer:/root/.composer/cache/files:rw" + - "/tmp/base_cache:/tmp/base_cache:rw" - shared-volume:/tmp/docker working_dir: /imi command: tail -f /dev/null diff --git a/.github/workflows/daily-test.yml b/.github/workflows/daily-test.yml index f805a2f9ad..5a8f9d1cdb 100644 --- a/.github/workflows/daily-test.yml +++ b/.github/workflows/daily-test.yml @@ -1,24 +1,28 @@ -name: daily-test +name: Daily Test on: schedule: - cron: "0 16 * * *" # 这个值是 UTC 时间,每天北京时间 0 点执行 + push: + paths: + - ".github/workflows/daily-test.yml" + pull_request: + paths: + - ".github/workflows/daily-test.yml" jobs: - ci: - name: Linux PHP-${{ matrix.php }} Swoole-${{ matrix.swoole.version }} RoadRunner-${{ matrix.roadrunner }} - runs-on: ubuntu-20.04 + daily-test-3_0: + name: 3.0_Linux PHP-${{ matrix.php }} Swoole-${{ matrix.swoole.version }} RoadRunner-${{ matrix.roadrunner }} + runs-on: ubuntu-latest strategy: fail-fast: false matrix: php: [8.2] swoole: - version: master - postgresql_version: "" roadrunner: [2.7.*] env: ENV_SERVICE: php - POSTGRESQL_VERSION: ${{ matrix.swoole.postgresql_version }} PHP_VERSION: ${{ matrix.php }} SWOOLE_VERSION: ${{ matrix.swoole.version }} MYSQL_DOCKER_VERSION: "8.0" @@ -29,11 +33,16 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + ref: "3.0" - name: Cache dependencies uses: actions/cache@v3 with: - path: /tmp/composer - key: ${{ runner.os }}-composer-${{ matrix.swoole.version }}-${{ hashFiles('/composer.json') }} + path: /tmp/base_cache/composer + key: ${{ runner.os }}-daily-test-3.0-composer-${{ matrix.php }}-${{ hashFiles('*/composer.json', 'src/Components/*/composer.json') }} + restore-keys: | + ${{ runner.os }}-daily-test-3.0-composer-${{ matrix.php }}- + ${{ runner.os }}-daily-test-3.0-composer- - name: Prepare uses: ./.github/actions/ci-prepare with: @@ -89,3 +98,91 @@ jobs: - name: Print logs if: failure() run: docker exec ${ENV_SERVICE} php .github/print-logs.php + + daily-test-2_1: + name: 2.1_Linux PHP-${{ matrix.php }} Swoole-${{ matrix.swoole.version }} RoadRunner-${{ matrix.roadrunner }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: [ 8.2 ] + swoole: + - version: master + roadrunner: [ 2.7.* ] + env: + ENV_SERVICE: php + PHP_VERSION: ${{ matrix.php }} + SWOOLE_VERSION: ${{ matrix.swoole.version }} + MYSQL_DOCKER_VERSION: "8.0" + REDIS_SERVER_HOST: redis + ROADRUNNER_DOCKER_VERSION: ${{ matrix.roadrunner }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COMPOSER_ENV: --ignore-platform-reqs + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: "2.1" + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: /tmp/base_cache/composer + key: ${{ runner.os }}-daily-test-2.1-composer-${{ matrix.php }}-${{ hashFiles('*/composer.json', 'src/Components/*/composer.json') }} + restore-keys: | + ${{ runner.os }}-daily-test-2.1-composer-${{ matrix.php }}- + ${{ runner.os }}-daily-test-2.1-composer- + - name: Prepare + uses: ./.github/actions/ci-prepare + with: + env: ${{ env.ENV_SERVICE }} + - name: Test + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test + - name: Test swoole + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-swoole + - name: Test workerman + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-workerman + - name: Test workerman-gateway + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-workerman-gateway + - name: Test roadrunner + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-roadrunner + - name: Test fpm + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-fpm + - name: Test jwt + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-jwt + - name: Test queue + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-queue + - name: Test amqp + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-amqp + - name: Test kafka + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-kafka + - name: Test grpc + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-grpc + - name: Test snowflake + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-snowflake + - name: Test mqtt + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-mqtt + - name: Test smarty + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-smarty + - name: Test pgsql + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-pgsql + - name: Test phar + if: ${{ env.test_prepared && always() }} + run: docker exec ${ENV_SERVICE} composer test-phar + - name: Print logs + if: failure() + run: docker exec ${ENV_SERVICE} php .github/print-logs.php \ No newline at end of file From cb07e0e85f843da5099177a634a0fc910271dc8d Mon Sep 17 00:00:00 2001 From: Yurun Date: Tue, 14 Nov 2023 19:57:22 +0800 Subject: [PATCH 6/9] =?UTF-8?q?[3.0]=20=E9=87=8D=E6=9E=84=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE=EF=BC=8C=E4=BD=BF=E7=94=A8=E5=8E=9F=E7=94=9F=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE=20(#648)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 重构 AMQP 枚举 * 重构 pgsql 枚举 * 重构 CronTaskType * 重构 Imi\Cron\Consts\UniqueLevel 枚举 * 重构 Imi\Db\Mysql\Consts\LogicalOperator * 重构 Imi\Db\Mysql\Query\FullText\SearchModifier * 修复 * 重构 Imi\Model\IdGenerator\UUIDGeneratorType * 更新文档 * 修复 * 重构 Imi\Server\WebSocket\Enum::NonControlFrameType 枚举 * PHP 原生枚举深度支持 (#646) * beans 配置注入支持枚举 * InEnum 验证器支持原生枚举 * 修复 * 修复 * 修复一个类有多个Bean名称时,beans 注入的属性值不正确 * 完善测试 * 修复 * 修复 # Conflicts: # phpstan.neon # src/Bean/BeanProxy.php # src/Validate/ValidatorHelper.php * 修复 * 修复 * 调整命名 --- doc/base/config.md | 4 +- doc/base/version/2.1-3.0.md | 14 ++ doc/components/orm/RDModel/definition.md | 8 +- doc/components/struct/enum.md | 4 +- doc/components/task/cron.md | 6 +- doc/container/workerman.md | 4 +- doc/container/workerman/serverConfig.md | 4 +- doc/core/long-connection-distributed.md | 4 +- doc/core/subServer.md | 4 +- src/Bean/BeanFactory.php | 42 ++++-- src/Bean/BeanProxy.php | 120 +++++++++++++----- src/Bean/Container.php | 2 +- .../amqp/example/AMQP/Test/TestConsumer.php | 4 +- src/Components/amqp/src/Base/BaseConsumer.php | 16 +-- .../amqp/src/Enum/ConsumerResult.php | 34 +++-- .../amqp/src/Queue/AMQPQueueDriver.php | 3 +- .../amqp/src/Queue/AMQPQueueDriverHandler.php | 27 ++-- .../amqp/src/Queue/QueueConsumer.php | 5 +- .../amqp/src/Queue/SwooleQueueConsumer.php | 5 +- .../kafka/src/Queue/KafkaQueueDriver.php | 3 +- .../pgsql/src/Db/Query/FullText/TsQuery.php | 11 +- .../pgsql/src/Db/Query/FullText/TsRank.php | 11 +- .../src/Annotation/QueueTypeStructType.php | 20 --- .../queue/src/Driver/IQueueDriver.php | 5 +- .../queue/src/Driver/RedisQueueDriver.php | 65 +++++----- .../src/Driver/RedisStreamQueueDriver.php | 3 +- src/Components/queue/src/Enum/IQueueType.php | 13 ++ src/Components/queue/src/Enum/QueueType.php | 70 +++++----- .../swoole/src/Cron/Consts/CronTaskType.php | 9 +- .../swoole/src/Cron/CronManager.php | 3 +- .../Server/Util/Amqp/AmqpServerConsumer.php | 8 +- .../swoole/src/Server/Util/AmqpServerUtil.php | 4 +- .../src/Server/Util/LocalServerUtil.php | 6 +- .../swoole/src/Server/WebSocket/Server.php | 6 +- .../unit/WebSocketServer/config/config.php | 2 +- .../Server/Gateway/GatewayServer.php | 8 +- .../tests/unit/AppServer/config/config.php | 2 +- .../workerman/src/Server/WebSocket/Server.php | 8 +- .../tests/unit/AppServer/config/config.php | 2 +- src/Cron/Annotation/Cron.php | 3 +- src/Cron/Consts/CronTaskType.php | 6 +- src/Cron/Consts/UniqueLevel.php | 19 ++- src/Cron/Contract/ICronManager.php | 3 +- src/Cron/CronLock.php | 4 +- src/Cron/CronManager.php | 3 +- src/Cron/CronTask.php | 11 +- src/Db/Mysql/Consts/LogicalOperator.php | 23 ++-- .../Mysql/Query/FullText/SearchModifier.php | 23 ++-- src/Db/Query/Traits/TWhereCollector.php | 12 +- src/Model/IdGenerator/UUIDGenerator.php | 13 +- src/Model/IdGenerator/UUIDGeneratorType.php | 14 +- .../WebSocket/Contract/IWebSocketServer.php | 3 +- src/Server/WebSocket/Dispatcher.php | 2 +- .../WebSocket/Enum/NonControlFrameType.php | 19 ++- src/Util/EnumUtil.php | 48 +++++++ src/Validate/ValidatorHelper.php | 17 ++- tests/unit/Component/Bean/EnumBean.php | 38 ++++++ tests/unit/Component/Enum/TestEnumBean.php | 11 ++ .../Component/Enum/TestEnumBeanBacked.php | 11 ++ tests/unit/Component/Model/ArticleId.php | 3 +- tests/unit/Component/Tests/BeanTest.php | 29 +++++ tests/unit/Component/Tests/Util/EnumTest.php | 37 ++++++ .../Component/Tests/ValidatorHelperTest.php | 14 ++ tests/unit/Component/config/config.php | 10 ++ 64 files changed, 610 insertions(+), 335 deletions(-) delete mode 100644 src/Components/queue/src/Annotation/QueueTypeStructType.php create mode 100644 src/Components/queue/src/Enum/IQueueType.php create mode 100644 src/Util/EnumUtil.php create mode 100644 tests/unit/Component/Bean/EnumBean.php create mode 100644 tests/unit/Component/Enum/TestEnumBean.php create mode 100644 tests/unit/Component/Enum/TestEnumBeanBacked.php create mode 100644 tests/unit/Component/Tests/Util/EnumTest.php diff --git a/doc/base/config.md b/doc/base/config.md index 420cfc6617..006cbd3d66 100644 --- a/doc/base/config.md +++ b/doc/base/config.md @@ -147,8 +147,8 @@ return [ // 参考: http://wiki.swoole.com/#/server/setting // 参考: http://wiki.swoole.com/#/websocket_server?id=%e9%80%89%e9%a1%b9 // 参考: http://wiki.swoole.com/#/http_server?id=%e9%85%8d%e7%bd%ae%e9%80%89%e9%a1%b9 - 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::TEXT, // 配置 WebSocket 纯文本通信协议 - // 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::BINARY, // 配置 WebSocket 二进制通信协议 + 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::Text, // 配置 WebSocket 纯文本通信协议 + // 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::Binary, // 配置 WebSocket 二进制通信协议 'configs' => [ 'reactor_num' => 8, 'worker_num' => 8, diff --git a/doc/base/version/2.1-3.0.md b/doc/base/version/2.1-3.0.md index fb29d84c6a..5b629b5fbe 100644 --- a/doc/base/version/2.1-3.0.md +++ b/doc/base/version/2.1-3.0.md @@ -69,6 +69,16 @@ return [ * 重构注解类写法 +* 定时任务 `Imi\Cron\Annotation\Cron` 注解的 `unique` 值类型更改为 `\Imi\Cron\Consts\UniqueLevel` 枚举,大小写有所变化 + +### 模型 + +* UUID 发号器的 `type` 类型改为枚举,大小写有所变化 + +### WebSocket + +* 重构 `Imi\Server\WebSocket\Enum::NonControlFrameType` 为枚举 + ### imi-access-control 废弃并移出主仓库,代码仓库: @@ -81,6 +91,10 @@ return [ * 废弃 `Imi\AMQP\Swoole\AMQPSwooleConnection` 客户端类 +* 消费者类 `Imi\AMQP\Base\BaseConsumer::consume()` 方法返回值类型应设置为 `\Imi\AMQP\Enum\ConsumerResult`,且必须返回枚举值 + +* `Imi\Queue\Enum\QueueType` 改为原生注解,如需自定义请编写枚举并实现 `Imi\Queue\Enum\QueueType\IQueueType` 接口 + ### imi-macro 废弃并移出主仓库,代码仓库: diff --git a/doc/components/orm/RDModel/definition.md b/doc/components/orm/RDModel/definition.md index ab6acbf053..3a52aa32f9 100644 --- a/doc/components/orm/RDModel/definition.md +++ b/doc/components/orm/RDModel/definition.md @@ -550,19 +550,19 @@ ID 生成器指定参数: `#[Id(generator: \Imi\Model\IdGenerator\UUIDGenerator::class)]` -`#[Id(generator: \Imi\Model\IdGenerator\UUIDGenerator::class, generatorOptions: ["type" => \Imi\Model\IdGenerator\UUIDGeneratorType::TIME])]` +`#[Id(generator: \Imi\Model\IdGenerator\UUIDGenerator::class, generatorOptions: ["type" => \Imi\Model\IdGenerator\UUIDGeneratorType::Time])]` -**随机算法:**`#[Id(generator: \Imi\Model\IdGenerator\UUIDGenerator::class, generatorOptions: ["type" => \Imi\Model\IdGenerator\UUIDGeneratorType::RANDOM])]` +**随机算法:**`#[Id(generator: \Imi\Model\IdGenerator\UUIDGenerator::class, generatorOptions: ["type" => \Imi\Model\IdGenerator\UUIDGeneratorType::Random])]` **MD5、Sha1:** 使用方法基本一样,差别就是 `generatorOptions.type` 值不同。 -`#[Id(index: false, generator: \Imi\Model\IdGenerator\UUIDGenerator::class, generatorOptions: ["type" => \Imi\Model\IdGenerator\UUIDGeneratorType::MD5, "ns" => "99e4edaf-8363-466e-bddf-7254db57675c", "nameField" => "名称字段名,该字段值必须唯一,否则会重复"])]` +`#[Id(index: false, generator: \Imi\Model\IdGenerator\UUIDGenerator::class, generatorOptions: ["type" => \Imi\Model\IdGenerator\UUIDGeneratorType::Md5, "ns" => "99e4edaf-8363-466e-bddf-7254db57675c", "nameField" => "名称字段名,该字段值必须唯一,否则会重复"])]` > `ns` 必须是一个合法的 UUID -`#[Id(index: false, generator: \Imi\Model\IdGenerator\UUIDGenerator::class, generatorOptions: ["type" => \Imi\Model\IdGenerator\UUIDGeneratorType::SHA1, "nsField" => "命名空间字段名", "name" => "直接指定名称"])]` +`#[Id(index: false, generator: \Imi\Model\IdGenerator\UUIDGenerator::class, generatorOptions: ["type" => \Imi\Model\IdGenerator\UUIDGeneratorType::Sha1, "nsField" => "命名空间字段名", "name" => "直接指定名称"])]` > 注意:`ns`、`name` 的值如果一样,生成的 UUID 也会一样!!! diff --git a/doc/components/struct/enum.md b/doc/components/struct/enum.md index 810e0b05b1..de211b7b35 100644 --- a/doc/components/struct/enum.md +++ b/doc/components/struct/enum.md @@ -2,7 +2,9 @@ [toc] -由于 PHP 本身不支持枚举类型,imi 特别基于注解实现了枚举类。 +由于 PHP < 8.1 本身不支持枚举类型,imi 特别基于注解实现了枚举类。 + +> 此功能在 3.0 不会被内置,需要手动安装 `imi-old-enum` 组件。强烈建议使用 PHP 原生枚举! ## 枚举类定义 diff --git a/doc/components/task/cron.md b/doc/components/task/cron.md index 82fa9d2d41..9d41fe5178 100644 --- a/doc/components/task/cron.md +++ b/doc/components/task/cron.md @@ -339,9 +339,9 @@ class TaskProcess implements IProcess **unique:** 定时任务唯一性设置 -当前实例唯一: current -所有实例唯一: all -不唯一: null +当前实例唯一: `\Imi\Cron\Consts\UniqueLevel::Current` +所有实例唯一: `\Imi\Cron\Consts\UniqueLevel::All` +不唯一: `null` **redisPool:** diff --git a/doc/container/workerman.md b/doc/container/workerman.md index b99d8aa025..575f1edd5a 100644 --- a/doc/container/workerman.md +++ b/doc/container/workerman.md @@ -46,8 +46,8 @@ imi v2.0 版本开始,支持运行在 Workerman 环境中。 'namespace' => 'Imi\WorkermanGateway\Test\AppServer\Gateway', 'type' => Imi\WorkermanGateway\Workerman\Server\Type::GATEWAY, 'socketName' => 'websocket://0.0.0.0:8081', // 网关监听的地址 - 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::TEXT, // 配置 WebSocket 纯文本通信协议 - // 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::BINARY, // 配置 WebSocket 二进制通信协议 + 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::Text, // 配置 WebSocket 纯文本通信协议 + // 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::Binary, // 配置 WebSocket 二进制通信协议 'configs' => [ 'lanIp' => '127.0.0.1', 'startPort' => 12900, diff --git a/doc/container/workerman/serverConfig.md b/doc/container/workerman/serverConfig.md index e9855e36d1..98ed77e026 100644 --- a/doc/container/workerman/serverConfig.md +++ b/doc/container/workerman/serverConfig.md @@ -47,8 +47,8 @@ return [ 'host' => '0.0.0.0', 'port' => 13002, 'shareWorker' => 'http', // 与名字叫 http 的服务,共享 worker 进程 - 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::TEXT, // 配置 WebSocket 纯文本通信协议 - // 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::BINARY, // 配置 WebSocket 二进制通信协议 + 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::Text, // 配置 WebSocket 纯文本通信协议 + // 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::Binary, // 配置 WebSocket 二进制通信协议 'configs' => [ ], ], diff --git a/doc/core/long-connection-distributed.md b/doc/core/long-connection-distributed.md index 853b16caf3..0d2dffc183 100644 --- a/doc/core/long-connection-distributed.md +++ b/doc/core/long-connection-distributed.md @@ -242,8 +242,8 @@ Workerman Gateway 是一个成熟的实现方案,可以实现分布式消息 'namespace' => 'Imi\WorkermanGateway\Test\AppServer\Gateway', 'type' => Imi\WorkermanGateway\Workerman\Server\Type::GATEWAY, 'socketName' => 'websocket://0.0.0.0:13002', - 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::TEXT, // 配置 WebSocket 纯文本通信协议 - // 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::BINARY, // 配置 WebSocket 二进制通信协议 + 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::Text, // 配置 WebSocket 纯文本通信协议 + // 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::Binary, // 配置 WebSocket 二进制通信协议 'configs' => [ 'lanIp' => '127.0.0.1', 'startPort' => 12900, diff --git a/doc/core/subServer.md b/doc/core/subServer.md index d9fbe91988..5f2210adb3 100644 --- a/doc/core/subServer.md +++ b/doc/core/subServer.md @@ -32,8 +32,8 @@ http 和 WebSocket 同时做在一个项目中,代码之间没有隔阂,可 'sockType' => SWOOLE_SOCK_TCP, // 同步连接,当连接事件执行完后,才执行 receive 事件。仅 TCP、WebSocket 且 SWOOLE_BASE 模式有效 'syncConnect' => true, - 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::TEXT, // 配置 WebSocket 纯文本通信协议 - // 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::BINARY, // 配置 WebSocket 二进制通信协议 + 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::Text, // 配置 WebSocket 纯文本通信协议 + // 'nonControlFrameType' => \Imi\Server\WebSocket\Enum\NonControlFrameType::Binary, // 配置 WebSocket 二进制通信协议 // 服务器配置,参数用法同\Swoole\Server->set($configs) 'configs' => [ ], diff --git a/src/Bean/BeanFactory.php b/src/Bean/BeanFactory.php index 06bf103cba..229a2f686e 100644 --- a/src/Bean/BeanFactory.php +++ b/src/Bean/BeanFactory.php @@ -37,8 +37,20 @@ class BeanFactory */ public static function newInstance(string $class, mixed ...$args): mixed { - $object = self::newInstanceNoInit($class, ...$args); - static::initInstance($object, $args); + return static::newBeanInstance($class, null, ...$args); + } + + /** + * 实例化. + * + * @template T + * + * @param class-string $class + */ + public static function newBeanInstance(string $class, ?string $beanName = null, mixed ...$args): mixed + { + $object = static::newInstanceNoInit($class, ...$args); + static::initInstance($object, $args, $beanName); return $object; } @@ -61,7 +73,7 @@ public static function newInstanceNoInit(string $class, mixed ...$args): mixed } else { - if (self::$enableFileCache) + if (static::$enableFileCache) { static::parseEvalName($class, $fileName, $className); if (is_file($fileName)) @@ -100,8 +112,20 @@ public static function newInstanceNoInit(string $class, mixed ...$args): mixed */ public static function newInstanceEx(string $class, array $args = []): mixed { - $object = self::newInstanceExNoInit($class, $args, $resultArgs); - static::initInstance($object, $resultArgs); + return static::newBeanInstanceEx($class, null, $args); + } + + /** + * 增强实例化. + * + * @template T + * + * @param class-string $class + */ + public static function newBeanInstanceEx(string $class, ?string $beanName = null, array $args = []): mixed + { + $object = static::newInstanceExNoInit($class, $args, $resultArgs); + static::initInstance($object, $resultArgs, $beanName); return $object; } @@ -135,16 +159,16 @@ public static function newInstanceExNoInit(string $class, array $args, ?array &$ } } - return self::newInstanceNoInit($class, ...$resultArgs); + return static::newInstanceNoInit($class, ...$resultArgs); } /** * 初始化Bean对象 */ - public static function initInstance(object $object, array $args = []): void + public static function initInstance(object $object, array $args = [], ?string $beanName = null): void { - $class = self::getObjectClass($object); - BeanProxy::injectProps($object, $class); + $class = static::getObjectClass($object); + BeanProxy::injectProps($object, $class, false, $beanName); $ref = ReflectionContainer::getClassReflection($class); if ($ref->hasMethod('__init')) { diff --git a/src/Bean/BeanProxy.php b/src/Bean/BeanProxy.php index d0856bb6e8..affd0baa66 100644 --- a/src/Bean/BeanProxy.php +++ b/src/Bean/BeanProxy.php @@ -17,6 +17,7 @@ use Imi\Aop\JoinPoint; use Imi\Aop\Model\AopItem; use Imi\Config; +use Imi\Util\EnumUtil; use Imi\Util\Imi; class BeanProxy @@ -135,9 +136,9 @@ public static function &call(object $object, string $className, string $method, /** * 注入属性. */ - public static function injectProps(object $object, string $className, bool $reInit = false): void + public static function injectProps(object $object, string $className, bool $reInit = false, ?string $beanName = null): void { - [$injects, $configs] = static::getInjects($className); + [$injects, $configs] = static::getInjects($className, $beanName); if (!$injects && !$configs) { return; @@ -169,6 +170,44 @@ public static function injectProps(object $object, string $className, bool $reIn { $propRef = $refClass->getProperty($name); $propRef->setAccessible(true); + if ($propRef->hasType()) + { + $type = $propRef->getType(); + foreach ((static function () use ($type) { + if ($type instanceof \ReflectionNamedType) + { + if (is_subclass_of($typeName = $type->getName(), \UnitEnum::class)) + { + yield $typeName; + } + } + elseif ($type instanceof \ReflectionUnionType) + { + foreach ($type->getTypes() as $type) + { + if (is_subclass_of($typeName = $type->getName(), \UnitEnum::class)) + { + yield $typeName; + } + } + } + })() as $enumType) + { + if (is_subclass_of($enumType, \BackedEnum::class)) + { + $case = $enumType::tryFrom($value); + } + else + { + $case = EnumUtil::tryFromName($enumType, $value); + } + if ($case) + { + $value = $case; + break; + } + } + } $propRef->setValue($object, $value); } } @@ -177,37 +216,54 @@ public static function injectProps(object $object, string $className, bool $reIn /** * 获取注入属性的配置们. */ - public static function getConfigInjects(string $className): array + public static function getConfigInjects(string $className, ?string $beanName = null): array { - // 配置文件注入 - $beanData = BeanManager::get($className); - if ($beanData) - { - $beanName = $beanData['beanName']; - } - else - { - $beanName = $className; - } - $beans = Config::get('@currentServer.beans'); - if (isset($beans[$beanName])) + $originBeanName = $beanName; + $count = 2; + while ($count--) { - return $beans[$beanName]; - } - elseif ($beanName !== $className && isset($beans[$className])) - { - return $beans[$className]; - } - else - { - $beans = Config::get('@app.beans'); - if (isset($beans[$beanName])) + // 配置文件注入 + if (null === $beanName) + { + $beanData = BeanManager::get($className); + if ($beanData) + { + $beanName = $beanData['beanName']; + } + else + { + $beanName = $className; + } + } + $serverBeans ??= Config::get('@currentServer.beans'); + if (isset($serverBeans[$beanName])) { - return $beans[$beanName]; + return $serverBeans[$beanName]; } - elseif ($beanName !== $className && isset($beans[$className])) + elseif ($beanName !== $className && isset($serverBeans[$className])) + { + return $serverBeans[$className]; + } + else + { + $appBeans ??= Config::get('@app.beans'); + if (isset($appBeans[$beanName])) + { + return $appBeans[$beanName]; + } + elseif ($beanName !== $className && isset($appBeans[$className])) + { + return $appBeans[$className]; + } + } + if (null === $originBeanName) + { + break; + } + else { - return $beans[$className]; + // 下次循环会根据类名尝试获取注入配置 + $beanName = null; } } @@ -219,9 +275,9 @@ public static function getConfigInjects(string $className): array * * 返回:[$annotations, $configs] */ - public static function getInjects(string $className): array + public static function getInjects(string $className, ?string $beanName = null): array { - $configs = static::getConfigInjects($className); + $configs = static::getConfigInjects($className, $beanName); $injects = BeanManager::getPropertyInjects($className); if ($configs && $injects) { @@ -301,9 +357,9 @@ private static function doAspect(string $className, string $method, string $poin /** * 获取注入类属性的值 */ - public static function getInjectValue(string $className, string $propertyName): mixed + public static function getInjectValue(string $className, string $propertyName, ?string $beanName = null): mixed { - [$annotations, $configs] = static::getInjects($className); + [$annotations, $configs] = static::getInjects($className, $beanName); if (isset($configs[$propertyName])) { return $configs[$propertyName]; diff --git a/src/Bean/Container.php b/src/Bean/Container.php index 1d65e01fe2..9bc4601030 100644 --- a/src/Bean/Container.php +++ b/src/Bean/Container.php @@ -163,7 +163,7 @@ private function __newInstance(string $id, array $params, bool $allowStore): mix if ($data['recursion'] ?? true) { // @phpstan-ignore-next-line - BeanFactory::initInstance($object, $params); + BeanFactory::initInstance($object, $params, $originId); if ($stored && $object !== $beanObjects[$originId]) { // 防止类 __init() 方法有协程上下文切换,导致单例被覆盖 diff --git a/src/Components/amqp/example/AMQP/Test/TestConsumer.php b/src/Components/amqp/example/AMQP/Test/TestConsumer.php index f54684388a..bdd7e5730c 100644 --- a/src/Components/amqp/example/AMQP/Test/TestConsumer.php +++ b/src/Components/amqp/example/AMQP/Test/TestConsumer.php @@ -23,11 +23,11 @@ class TestConsumer extends BaseConsumer * * @param \AMQPApp\AMQP\Test\TestMessage $message */ - protected function consume(IMessage $message): mixed + protected function consume(IMessage $message): ConsumerResult { var_dump(__CLASS__, $message->getBody(), $message::class); Redis::set('imi-amqp:consume:1:' . $message->getMemberId(), $message->getBody()); - return ConsumerResult::ACK; + return ConsumerResult::Ack; } } diff --git a/src/Components/amqp/src/Base/BaseConsumer.php b/src/Components/amqp/src/Base/BaseConsumer.php index bd71148b86..9290f2ee09 100644 --- a/src/Components/amqp/src/Base/BaseConsumer.php +++ b/src/Components/amqp/src/Base/BaseConsumer.php @@ -100,7 +100,7 @@ protected function bindConsumer(): void return; } ++$this->messageCount; - $result = ConsumerResult::NACK; + $result = ConsumerResult::Nack; try { /** @var \Imi\AMQP\Message $messageInstance */ @@ -117,7 +117,7 @@ protected function bindConsumer(): void { Log::error($th); - return ConsumerResult::NACK; + return ConsumerResult::Nack; } }); } @@ -134,19 +134,19 @@ protected function bindConsumer(): void { switch ($result) { - case ConsumerResult::ACK: + case ConsumerResult::Ack: $this->channel->basic_ack($message->getDeliveryTag()); break; - case ConsumerResult::NACK: + case ConsumerResult::Nack: $this->channel->basic_nack($message->getDeliveryTag()); break; - case ConsumerResult::NACK_REQUEUE: + case ConsumerResult::NackRequeue: $this->channel->basic_nack($message->getDeliveryTag(), false, true); break; - case ConsumerResult::REJECT: + case ConsumerResult::Reject: $this->channel->basic_reject($message->getDeliveryTag(), false); break; - case ConsumerResult::REJECT_REQUEUE: + case ConsumerResult::RejectRequeue: $this->channel->basic_reject($message->getDeliveryTag(), true); break; } @@ -159,5 +159,5 @@ protected function bindConsumer(): void /** * 消费任务 */ - abstract protected function consume(IMessage $message): mixed; + abstract protected function consume(IMessage $message): ConsumerResult; } diff --git a/src/Components/amqp/src/Enum/ConsumerResult.php b/src/Components/amqp/src/Enum/ConsumerResult.php index 30013739ec..aa9e08023b 100644 --- a/src/Components/amqp/src/Enum/ConsumerResult.php +++ b/src/Components/amqp/src/Enum/ConsumerResult.php @@ -4,37 +4,33 @@ namespace Imi\AMQP\Enum; -use Imi\Enum\Annotation\EnumItem; -use Imi\Enum\BaseEnum; - /** * 消费者执行结果. */ -class ConsumerResult extends BaseEnum +enum ConsumerResult: int { - use \Imi\Util\Traits\TStaticClass; - /** - * 用于消息消费成功 + * 确认消息. */ - #[EnumItem(text: '确认消息')] - public const ACK = 1; + case Ack = 1; /** - * 用于消息消费失败. + * 否定消息. */ - #[EnumItem(text: '否定消息')] - public const NACK = 2; + case Nack = 2; /** - * 用于消息消费失败,并重回队列. + * 否定消息,并重回队列. */ - #[EnumItem(text: '否定消息,并重回队列')] - public const NACK_REQUEUE = 3; + case NackRequeue = 3; - #[EnumItem(text: '拒绝消息')] - public const REJECT = 4; + /** + * 拒绝消息. + */ + case Reject = 4; - #[EnumItem(text: '拒绝消息,并重回队列')] - public const REJECT_REQUEUE = 5; + /** + * 拒绝消息,并重回队列. + */ + case RejectRequeue = 5; } diff --git a/src/Components/amqp/src/Queue/AMQPQueueDriver.php b/src/Components/amqp/src/Queue/AMQPQueueDriver.php index 42f06521c9..501bc606ab 100644 --- a/src/Components/amqp/src/Queue/AMQPQueueDriver.php +++ b/src/Components/amqp/src/Queue/AMQPQueueDriver.php @@ -8,6 +8,7 @@ use Imi\Bean\BeanFactory; use Imi\Queue\Contract\IMessage; use Imi\Queue\Driver\IQueueDriver; +use Imi\Queue\Enum\IQueueType; use Imi\Queue\Model\QueueStatus; use Imi\RequestContext; use Imi\Util\Traits\TDataToProperty; @@ -153,7 +154,7 @@ public function delete(IMessage $message): bool /** * {@inheritDoc} */ - public function clear($queueType = null): void + public function clear(?IQueueType $queueType = null): void { $this->getHandler()->clear($queueType); } diff --git a/src/Components/amqp/src/Queue/AMQPQueueDriverHandler.php b/src/Components/amqp/src/Queue/AMQPQueueDriverHandler.php index 6bb7093157..ff15466581 100644 --- a/src/Components/amqp/src/Queue/AMQPQueueDriverHandler.php +++ b/src/Components/amqp/src/Queue/AMQPQueueDriverHandler.php @@ -8,6 +8,7 @@ use Imi\Bean\BeanFactory; use Imi\Queue\Contract\IMessage; use Imi\Queue\Driver\IQueueDriver; +use Imi\Queue\Enum\IQueueType; use Imi\Queue\Enum\QueueType; use Imi\Queue\Exception\QueueException; use Imi\Queue\Model\QueueStatus; @@ -333,7 +334,7 @@ public function pop(float $timeout = 0): ?IMessage } Redis::use(function (\Imi\Redis\RedisHandler $redis) use ($score, $message): void { - $redis->zAdd($this->getRedisQueueKey(QueueType::WORKING), $score, json_encode($message->toArray(), \JSON_THROW_ON_ERROR | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE)); + $redis->zAdd($this->getRedisQueueKey(QueueType::Working), $score, json_encode($message->toArray(), \JSON_THROW_ON_ERROR | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE)); }, $this->redisPoolName, true); return $message; @@ -359,12 +360,12 @@ public function delete(IMessage $message): bool /** * {@inheritDoc} */ - public function clear($queueType = null): void + public function clear(?IQueueType $queueType = null): void { Redis::use(function (\Imi\Redis\RedisHandler $redis) use ($queueType): void { if (null === $queueType) { - $queueTypes = QueueType::getValues(); + $queueTypes = QueueType::cases(); } else { @@ -376,7 +377,7 @@ public function clear($queueType = null): void { switch ($queueType) { - case QueueType::READY: + case QueueType::Ready: // 清空所有 while ($message = $this->pop()) { @@ -387,18 +388,18 @@ public function clear($queueType = null): void $this->consumer->reopen(); $redis->del($this->getRedisQueueKey('deleted')); break; - case QueueType::WORKING: - $redis->del($this->getRedisQueueKey(QueueType::WORKING)); + case QueueType::Working: + $redis->del($this->getRedisQueueKey(QueueType::Working)); break; - case QueueType::FAIL: + case QueueType::Fail: $this->failConsumer->getAMQPChannel()->queue_purge($this->failQueueName); $this->failConsumer->reopen(); break; - case QueueType::TIMEOUT: + case QueueType::Timeout: $this->timeoutConsumer->getAMQPChannel()->queue_purge($this->timeoutQueueName); $this->timeoutConsumer->reopen(); break; - case QueueType::DELAY: + case QueueType::Delay: $this->delayPublisher->getAMQPChannel()->queue_purge($this->delayQueueName); break; } @@ -475,7 +476,7 @@ public function status(): QueueStatus $status['ready'] = $ready; // working - $status['working'] = $redis->zCard($this->getRedisQueueKey(QueueType::WORKING)); + $status['working'] = $redis->zCard($this->getRedisQueueKey(QueueType::Working)); // fail $fail = 0; @@ -590,9 +591,9 @@ public function getRedisMessageIdKey(): string /** * 获取队列的键. */ - public function getRedisQueueKey(int|string $queueType): string + public function getRedisQueueKey(string|IQueueType $queueType): string { - return $this->redisPrefix . $this->name . ':' . strtolower(QueueType::getName($queueType) ?? $queueType); + return $this->redisPrefix . $this->name . ':' . strtolower($queueType->name ?? $queueType); } /** @@ -614,7 +615,7 @@ protected function parseTimeoutMessages(int $count = 100): void redis.call('zrem', KEYS[1], unpack(messages)) return messages LUA, [ - $this->getRedisQueueKey(QueueType::WORKING), + $this->getRedisQueueKey(QueueType::Working), microtime(true), $count, ], 1); diff --git a/src/Components/amqp/src/Queue/QueueConsumer.php b/src/Components/amqp/src/Queue/QueueConsumer.php index e3f0cc084b..9a619d4fa2 100644 --- a/src/Components/amqp/src/Queue/QueueConsumer.php +++ b/src/Components/amqp/src/Queue/QueueConsumer.php @@ -10,6 +10,7 @@ use Imi\AMQP\Base\BaseConsumer; use Imi\AMQP\Contract\IMessage; use Imi\AMQP\Contract\IQueueConsumer; +use Imi\AMQP\Enum\ConsumerResult; use Imi\AMQP\Message; class QueueConsumer extends BaseConsumer implements IQueueConsumer @@ -127,10 +128,10 @@ protected function bindConsumer(): void /** * {@inheritDoc} */ - protected function consume(IMessage $message): mixed + protected function consume(IMessage $message): ConsumerResult { $this->queue->push($message); - return null; + return ConsumerResult::Ack; } } diff --git a/src/Components/amqp/src/Queue/SwooleQueueConsumer.php b/src/Components/amqp/src/Queue/SwooleQueueConsumer.php index 3520c3c210..578f3dae59 100644 --- a/src/Components/amqp/src/Queue/SwooleQueueConsumer.php +++ b/src/Components/amqp/src/Queue/SwooleQueueConsumer.php @@ -10,6 +10,7 @@ use Imi\AMQP\Base\BaseConsumer; use Imi\AMQP\Contract\IMessage; use Imi\AMQP\Contract\IQueueConsumer; +use Imi\AMQP\Enum\ConsumerResult; use Imi\AMQP\Message; use Swoole\Coroutine\Channel; @@ -131,11 +132,11 @@ protected function bindConsumer(): void /** * {@inheritDoc} */ - protected function consume(IMessage $message): mixed + protected function consume(IMessage $message): ConsumerResult { $this->resultChannel->push($message); - return null; + return ConsumerResult::Ack; } } } diff --git a/src/Components/kafka/src/Queue/KafkaQueueDriver.php b/src/Components/kafka/src/Queue/KafkaQueueDriver.php index 88c5c3f5ad..847c33b65e 100644 --- a/src/Components/kafka/src/Queue/KafkaQueueDriver.php +++ b/src/Components/kafka/src/Queue/KafkaQueueDriver.php @@ -11,6 +11,7 @@ use Imi\Kafka\Queue\Model\KafkaPopMessage; use Imi\Queue\Contract\IMessage; use Imi\Queue\Driver\IQueueDriver; +use Imi\Queue\Enum\IQueueType; use Imi\Queue\Model\QueueStatus; use Imi\Util\Traits\TDataToProperty; use longlang\phpkafka\Consumer\Consumer; @@ -107,7 +108,7 @@ public function delete(IMessage $message): bool /** * {@inheritDoc} */ - public function clear($queueType = null): void + public function clear(?IQueueType $queueType = null): void { throw new \RuntimeException('Unsupport clear queue in KafkaQueueDriver'); } diff --git a/src/Components/pgsql/src/Db/Query/FullText/TsQuery.php b/src/Components/pgsql/src/Db/Query/FullText/TsQuery.php index 9eea83b9f5..a50dcf753d 100644 --- a/src/Components/pgsql/src/Db/Query/FullText/TsQuery.php +++ b/src/Components/pgsql/src/Db/Query/FullText/TsQuery.php @@ -4,23 +4,20 @@ namespace Imi\Pgsql\Db\Query\FullText; -use Imi\Enum\Annotation\EnumItem; -use Imi\Enum\BaseEnum; +use Imi\Util\Traits\TStaticClass; /** * PostgreSQL tsquery 函数. */ -class TsQuery extends BaseEnum +class TsQuery { - #[EnumItem(text: 'to_tsquery')] + use TStaticClass; + public const TO_TSQUERY = 'to_tsquery'; - #[EnumItem(text: 'plainto_tsquery')] public const PLAINTO_TSQUERY = 'plainto_tsquery'; - #[EnumItem(text: 'phraseto_tsquery')] public const PHRASETO_TSQUERY = 'phraseto_tsquery'; - #[EnumItem(text: 'websearch_to_tsquery')] public const WEBSEARCH_TO_TSQUERY = 'websearch_to_tsquery'; } diff --git a/src/Components/pgsql/src/Db/Query/FullText/TsRank.php b/src/Components/pgsql/src/Db/Query/FullText/TsRank.php index 4262d34635..d6e11b159c 100644 --- a/src/Components/pgsql/src/Db/Query/FullText/TsRank.php +++ b/src/Components/pgsql/src/Db/Query/FullText/TsRank.php @@ -4,17 +4,16 @@ namespace Imi\Pgsql\Db\Query\FullText; -use Imi\Enum\Annotation\EnumItem; -use Imi\Enum\BaseEnum; - /** * PostgreSQL ts_rank 函数. */ -class TsRank extends BaseEnum +use Imi\Util\Traits\TStaticClass; + +class TsRank { - #[EnumItem(text: 'ts_rank')] + use TStaticClass; + public const TS_RANK = 'ts_rank'; - #[EnumItem(text: 'ts_rank_cd')] public const TS_RANK_CD = 'ts_rank_cd'; } diff --git a/src/Components/queue/src/Annotation/QueueTypeStructType.php b/src/Components/queue/src/Annotation/QueueTypeStructType.php deleted file mode 100644 index db3b75c070..0000000000 --- a/src/Components/queue/src/Annotation/QueueTypeStructType.php +++ /dev/null @@ -1,20 +0,0 @@ - 0) { $args = [ - $this->getQueueKey(QueueType::DELAY), + $this->getQueueKey(QueueType::Delay), $this->getMessageKeyPrefix(), $this->getMessageIdKey(), microtime(true) + $delay, @@ -121,7 +120,7 @@ public function push(IMessage $message, float $delay = 0, array $options = []): else { $args = [ - $this->getQueueKey(QueueType::READY), + $this->getQueueKey(QueueType::Ready), $this->getMessageKeyPrefix(), $this->getMessageIdKey(), date('Ymd'), @@ -217,8 +216,8 @@ public function pop(float $timeout = 0): ?IMessage redis.call('zadd', KEYS[2], ARGV[1] + score, messageId) return hashResult LUA, [ - $this->getQueueKey(QueueType::READY), - $this->getQueueKey(QueueType::WORKING), + $this->getQueueKey(QueueType::Ready), + $this->getQueueKey(QueueType::Working), $this->getMessageKeyPrefix(), microtime(true), ], 3); @@ -277,8 +276,8 @@ public function delete(IMessage $message): bool end return true LUA, [ - $this->getQueueKey(QueueType::READY), - $this->getQueueKey(QueueType::DELAY), + $this->getQueueKey(QueueType::Ready), + $this->getQueueKey(QueueType::Delay), $this->getMessageKeyPrefix(), $message->getMessageId(), ], 3); @@ -302,11 +301,11 @@ public function delete(IMessage $message): bool /** * {@inheritDoc} */ - public function clear($queueType = null): void + public function clear(?IQueueType $queueType = null): void { if (null === $queueType) { - $queueType = QueueType::getValues(); + $queueType = QueueType::cases(); } else { @@ -338,9 +337,9 @@ public function success(IMessage $message): int redis.call('del', KEYS[2] .. ARGV[1]) return true LUA, [ - $this->getQueueKey(QueueType::WORKING), + $this->getQueueKey(QueueType::Working), $this->getMessageKeyPrefix(), - $this->getQueueKey(QueueType::TIMEOUT), + $this->getQueueKey(QueueType::Timeout), $message->getMessageId(), ], 3); @@ -372,8 +371,8 @@ public function fail(IMessage $message, bool $requeue = false): int redis.call('rpush', KEYS[2], ARGV[1]) return true LUA, [ - $this->getQueueKey(QueueType::WORKING), - $requeue ? $this->getQueueKey(QueueType::READY) : $this->getQueueKey(QueueType::FAIL), + $this->getQueueKey(QueueType::Working), + $requeue ? $this->getQueueKey(QueueType::Ready) : $this->getQueueKey(QueueType::Fail), $message->getMessageId(), ], 2); @@ -400,21 +399,15 @@ public function status(): QueueStatus { return Redis::use(function (\Imi\Redis\RedisHandler $redis) { $status = []; - foreach (QueueType::getMap() as $key => $value) + foreach (QueueType::cases() as $case) { - /** @var QueueTypeStructType|null $queueTypeStructTypeAnnotation */ - $queueTypeStructTypeAnnotation = AnnotationManager::getConstantAnnotations(QueueType::class, $key, QueueTypeStructType::class, onlyFirst: true); - if (!$queueTypeStructTypeAnnotation) + $count = match ($case->structType()) { - throw new \RuntimeException(sprintf('Unknown QueueTypeStructType of %s::%s', QueueType::class, $key)); - } - $count = match ($queueTypeStructTypeAnnotation->type) - { - 'list' => $redis->lLen($this->getQueueKey($value)), - 'zset' => $redis->zCard($this->getQueueKey($value)), - default => throw new QueueException('Invalid type ' . $queueTypeStructTypeAnnotation->type), + 'list' => $redis->lLen($this->getQueueKey($case)), + 'zset' => $redis->zCard($this->getQueueKey($case)), + default => throw new QueueException('Invalid type ' . $case->structType()), }; - $status[strtolower(QueueType::getName($value))] = $count; + $status[strtolower($case->name)] = $count; } return new QueueStatus($status); @@ -435,8 +428,8 @@ public function restoreFailMessages(): int end return result LUA, [ - $this->getQueueKey(QueueType::READY), - $this->getQueueKey(QueueType::FAIL), + $this->getQueueKey(QueueType::Ready), + $this->getQueueKey(QueueType::Fail), ], 2); if (false === $result) @@ -469,8 +462,8 @@ public function restoreTimeoutMessages(): int end return result LUA, [ - $this->getQueueKey(QueueType::READY), - $this->getQueueKey(QueueType::TIMEOUT), + $this->getQueueKey(QueueType::Ready), + $this->getQueueKey(QueueType::Timeout), ], 2); if (false === $result) @@ -509,8 +502,8 @@ protected function parseDelayMessages(\Imi\Redis\RedisHandler $redis, int $count redis.call('zrem', KEYS[2], unpack(messageIds)) return messageIdCount LUA, [ - $this->getQueueKey(QueueType::READY), - $this->getQueueKey(QueueType::DELAY), + $this->getQueueKey(QueueType::Ready), + $this->getQueueKey(QueueType::Delay), microtime(true), $count, ], 2); @@ -550,8 +543,8 @@ protected function parseTimeoutMessages(\Imi\Redis\RedisHandler $redis, int $cou redis.call('zrem', KEYS[1], unpack(messageIds)) return messageIdCount LUA, [ - $this->getQueueKey(QueueType::WORKING), - $this->getQueueKey(QueueType::TIMEOUT), + $this->getQueueKey(QueueType::Working), + $this->getQueueKey(QueueType::Timeout), microtime(true), $count, ], 2); @@ -590,8 +583,8 @@ public function getMessageIdKey(): string /** * 获取队列的键. */ - public function getQueueKey(int $queueType): string + public function getQueueKey(int|string|QueueType $queueType): string { - return $this->prefix . $this->keyName . ':' . strtolower(QueueType::getName($queueType)); + return $this->prefix . $this->keyName . ':' . strtolower($queueType instanceof QueueType ? $queueType->name : (string) $queueType); } } diff --git a/src/Components/queue/src/Driver/RedisStreamQueueDriver.php b/src/Components/queue/src/Driver/RedisStreamQueueDriver.php index dd91c8edd8..873b40f7c2 100644 --- a/src/Components/queue/src/Driver/RedisStreamQueueDriver.php +++ b/src/Components/queue/src/Driver/RedisStreamQueueDriver.php @@ -7,6 +7,7 @@ use Imi\Bean\Annotation\Bean; use Imi\Queue\Contract\IMessage; use Imi\Queue\Contract\IRedisStreamMessage; +use Imi\Queue\Enum\IQueueType; use Imi\Queue\Exception\QueueException; use Imi\Queue\Model\QueueStatus; use Imi\Queue\Model\RedisStreamMessage; @@ -205,7 +206,7 @@ public function delete(IMessage $message): bool /** * {@inheritDoc} */ - public function clear($queueType = null): void + public function clear(?IQueueType $queueType = null): void { Redis::use(function (\Imi\Redis\RedisHandler $redis): void { $redis->del($this->getQueueKey()); diff --git a/src/Components/queue/src/Enum/IQueueType.php b/src/Components/queue/src/Enum/IQueueType.php new file mode 100644 index 0000000000..ca0cc90ea7 --- /dev/null +++ b/src/Components/queue/src/Enum/IQueueType.php @@ -0,0 +1,13 @@ + 'list', + self::Working, self::Delay => 'zset', + }; + } } diff --git a/src/Components/swoole/src/Cron/Consts/CronTaskType.php b/src/Components/swoole/src/Cron/Consts/CronTaskType.php index c7e0b945be..f091995c06 100644 --- a/src/Components/swoole/src/Cron/Consts/CronTaskType.php +++ b/src/Components/swoole/src/Cron/Consts/CronTaskType.php @@ -4,27 +4,20 @@ namespace Imi\Swoole\Cron\Consts; -use Imi\Enum\Annotation\EnumItem; - /** * 定时任务类型. */ -class CronTaskType extends \Imi\Cron\Consts\CronTaskType +class CronTaskType { use \Imi\Util\Traits\TStaticClass; - #[EnumItem(text: '随机工作进程任务')] public const RANDOM_WORKER = 'random_worker'; - #[EnumItem(text: '所有工作进程执行的任务')] public const ALL_WORKER = 'all_worker'; - #[EnumItem(text: '后台任务')] public const TASK = 'task'; - #[EnumItem(text: '进程')] public const PROCESS = 'process'; - #[EnumItem(text: '定时任务进程')] public const CRON_PROCESS = 'cron_process'; } diff --git a/src/Components/swoole/src/Cron/CronManager.php b/src/Components/swoole/src/Cron/CronManager.php index 9871180d6e..a8bdd6fdbe 100644 --- a/src/Components/swoole/src/Cron/CronManager.php +++ b/src/Components/swoole/src/Cron/CronManager.php @@ -9,6 +9,7 @@ use Imi\Bean\Annotation\Bean; use Imi\Cli\ImiCommand; use Imi\Cron\Annotation\Cron; +use Imi\Cron\Consts\UniqueLevel; use Imi\Cron\Contract\ICronManager; use Imi\Cron\Contract\ICronTask; use Imi\Cron\CronTask; @@ -104,7 +105,7 @@ public function addCronByAnnotation(Cron $cron, string $pointClass): void /** * {@inheritDoc} */ - public function addCron(string $id, ?string $type, callable|string $task, array $cronRules, mixed $data, float $lockExpire = 3, ?string $unique = null, ?string $redisPool = null, float $lockWaitTimeout = 3, bool $force = false, bool $successLog = true): void + public function addCron(string $id, ?string $type, callable|string $task, array $cronRules, mixed $data, float $lockExpire = 3, ?UniqueLevel $unique = null, ?string $redisPool = null, float $lockWaitTimeout = 3, bool $force = false, bool $successLog = true): void { if (isset($this->tasks[$id])) { diff --git a/src/Components/swoole/src/Server/Util/Amqp/AmqpServerConsumer.php b/src/Components/swoole/src/Server/Util/Amqp/AmqpServerConsumer.php index 515f578bc4..ef75b4d0c5 100644 --- a/src/Components/swoole/src/Server/Util/Amqp/AmqpServerConsumer.php +++ b/src/Components/swoole/src/Server/Util/Amqp/AmqpServerConsumer.php @@ -68,7 +68,7 @@ public function unbindRoutingKey(string $routingKey): void /** * {@inheritDoc} */ - protected function consume(IMessage $message): mixed + protected function consume(IMessage $message): ConsumerResult { try { @@ -80,16 +80,16 @@ protected function consume(IMessage $message): mixed 'closeByFlag' => Server::closeByFlag($data['flag'], $serverName, false), 'sendRawToGroup' => Server::sendRawToGroup($data['group'], $data['data'], $serverName, false), 'sendRawToAll' => Server::sendRawToAll($data['data'], $serverName, false), - default => ConsumerResult::ACK, + default => ConsumerResult::Ack, }; - return ConsumerResult::ACK; + return ConsumerResult::Ack; } catch (\Throwable $th) { Log::error($th); - return ConsumerResult::NACK; + return ConsumerResult::Nack; } } } diff --git a/src/Components/swoole/src/Server/Util/AmqpServerUtil.php b/src/Components/swoole/src/Server/Util/AmqpServerUtil.php index 5c4483b966..63a1bb112b 100644 --- a/src/Components/swoole/src/Server/Util/AmqpServerUtil.php +++ b/src/Components/swoole/src/Server/Util/AmqpServerUtil.php @@ -158,7 +158,7 @@ public function sendRawToAll(string $data, ?string $serverName = null, bool $toA if ($server instanceof \Imi\Swoole\Server\WebSocket\Server) { $method = 'push'; - $pushParams = (array) $server->getNonControlFrameType(); + $pushParams = (array) $server->getNonControlFrameType()->value; } else { @@ -206,7 +206,7 @@ public function sendRawToGroup(string|array $groupName, string $data, ?string $s if ($server instanceof \Imi\Swoole\Server\WebSocket\Server) { $method = 'push'; - $pushParams = (array) $server->getNonControlFrameType(); + $pushParams = (array) $server->getNonControlFrameType()->value; } else { diff --git a/src/Components/swoole/src/Server/Util/LocalServerUtil.php b/src/Components/swoole/src/Server/Util/LocalServerUtil.php index a6d238477d..e40dc9003f 100644 --- a/src/Components/swoole/src/Server/Util/LocalServerUtil.php +++ b/src/Components/swoole/src/Server/Util/LocalServerUtil.php @@ -147,7 +147,7 @@ public function sendRaw(string $data, int|string|array|null $clientId = null, ?s if ($server instanceof \Imi\Swoole\Server\WebSocket\Server) { $method = 'push'; - $pushParams = (array) $server->getNonControlFrameType(); + $pushParams = (array) $server->getNonControlFrameType()->value; } else { @@ -268,7 +268,7 @@ public function sendRawToAll(string $data, ?string $serverName = null, bool $toA if ($server instanceof \Imi\Swoole\Server\WebSocket\Server) { $method = 'push'; - $pushParams = (array) $server->getNonControlFrameType(); + $pushParams = (array) $server->getNonControlFrameType()->value; } else { @@ -354,7 +354,7 @@ public function sendRawToGroup(string|array $groupName, string $data, ?string $s if ($server instanceof \Imi\Swoole\Server\WebSocket\Server) { $method = 'push'; - $pushParams = (array) $server->getNonControlFrameType(); + $pushParams = (array) $server->getNonControlFrameType()->value; } else { diff --git a/src/Components/swoole/src/Server/WebSocket/Server.php b/src/Components/swoole/src/Server/WebSocket/Server.php index 891ed6f521..f08ded3f25 100644 --- a/src/Components/swoole/src/Server/WebSocket/Server.php +++ b/src/Components/swoole/src/Server/WebSocket/Server.php @@ -56,7 +56,7 @@ class Server extends Base implements ISwooleWebSocketServer /** * 非控制帧类型. */ - private int $nonControlFrameType = NonControlFrameType::TEXT; + private NonControlFrameType $nonControlFrameType = NonControlFrameType::Text; /** * {@inheritDoc} @@ -65,7 +65,7 @@ public function __construct(string $name, array $config, bool $isSubServer = fal { parent::__construct($name, $config, $isSubServer); $this->syncConnect = $config['syncConnect'] ?? true; - $this->nonControlFrameType = $config['nonControlFrameType'] ?? NonControlFrameType::TEXT; + $this->nonControlFrameType = $config['nonControlFrameType'] ?? NonControlFrameType::Text; } /** @@ -363,7 +363,7 @@ public function push(int|string $clientId, string $data, int $opcode = 1): bool /** * {@inheritDoc} */ - public function getNonControlFrameType(): int + public function getNonControlFrameType(): NonControlFrameType { return $this->nonControlFrameType; } diff --git a/src/Components/swoole/tests/unit/WebSocketServer/config/config.php b/src/Components/swoole/tests/unit/WebSocketServer/config/config.php index 8358cf6c42..e4b03d032a 100644 --- a/src/Components/swoole/tests/unit/WebSocketServer/config/config.php +++ b/src/Components/swoole/tests/unit/WebSocketServer/config/config.php @@ -67,7 +67,7 @@ 'port' => 13002, 'mode' => \SWOOLE_BASE, 'syncConnect' => true, - 'nonControlFrameType' => NonControlFrameType::BINARY, + 'nonControlFrameType' => NonControlFrameType::Binary, 'configs' => [ 'worker_num' => 2, 'task_worker_num' => 1, diff --git a/src/Components/workerman-gateway/src/Workerman/Server/Gateway/GatewayServer.php b/src/Components/workerman-gateway/src/Workerman/Server/Gateway/GatewayServer.php index 7fc0352f4f..95768d9593 100644 --- a/src/Components/workerman-gateway/src/Workerman/Server/Gateway/GatewayServer.php +++ b/src/Components/workerman-gateway/src/Workerman/Server/Gateway/GatewayServer.php @@ -24,7 +24,7 @@ class GatewayServer extends \Imi\Workerman\Server\Tcp\Server /** * 非控制帧类型. */ - private int $nonControlFrameType = NonControlFrameType::TEXT; + private NonControlFrameType $nonControlFrameType = NonControlFrameType::Text; /** * {@inheritDoc} @@ -32,7 +32,7 @@ class GatewayServer extends \Imi\Workerman\Server\Tcp\Server public function __construct(string $name, array $config) { parent::__construct($name, $config); - $this->nonControlFrameType = $config['nonControlFrameType'] ?? NonControlFrameType::TEXT; + $this->nonControlFrameType = $config['nonControlFrameType'] ?? NonControlFrameType::Text; } /** @@ -45,7 +45,7 @@ protected function bindEvents(): void try { // @phpstan-ignore-next-line - $connection->websocketType = NonControlFrameType::TEXT === $this->nonControlFrameType ? Websocket::BINARY_TYPE_BLOB : Websocket::BINARY_TYPE_ARRAYBUFFER; + $connection->websocketType = NonControlFrameType::Text === $this->nonControlFrameType ? Websocket::BINARY_TYPE_BLOB : Websocket::BINARY_TYPE_ARRAYBUFFER; // @phpstan-ignore-next-line $clientId = $connection->id; RequestContext::muiltiSet([ @@ -69,7 +69,7 @@ protected function bindEvents(): void /** * Get 非控制帧类型. */ - public function getNonControlFrameType(): int + public function getNonControlFrameType(): NonControlFrameType { return $this->nonControlFrameType; } diff --git a/src/Components/workerman-gateway/tests/unit/AppServer/config/config.php b/src/Components/workerman-gateway/tests/unit/AppServer/config/config.php index d3ca8c6552..2826f48cec 100644 --- a/src/Components/workerman-gateway/tests/unit/AppServer/config/config.php +++ b/src/Components/workerman-gateway/tests/unit/AppServer/config/config.php @@ -113,7 +113,7 @@ 'namespace' => 'Imi\WorkermanGateway\Test\AppServer\Gateway', 'type' => Imi\WorkermanGateway\Workerman\Server\Type::GATEWAY, 'socketName' => 'websocket://127.0.0.1:13002', - 'nonControlFrameType' => NonControlFrameType::BINARY, + 'nonControlFrameType' => NonControlFrameType::Binary, 'configs' => [ 'lanIp' => '127.0.0.1', 'startPort' => 12900, diff --git a/src/Components/workerman/src/Server/WebSocket/Server.php b/src/Components/workerman/src/Server/WebSocket/Server.php index bcd3c52225..372ffb0f1e 100644 --- a/src/Components/workerman/src/Server/WebSocket/Server.php +++ b/src/Components/workerman/src/Server/WebSocket/Server.php @@ -31,7 +31,7 @@ class Server extends Base implements IWebSocketServer /** * 非控制帧类型. */ - private int $nonControlFrameType = NonControlFrameType::TEXT; + private NonControlFrameType $nonControlFrameType = NonControlFrameType::Text; /** * {@inheritDoc} @@ -40,7 +40,7 @@ public function __construct(string $name, array $config) { parent::__construct($name, $config); $this->worker->protocol = Websocket::class; - $this->nonControlFrameType = $config['nonControlFrameType'] ?? NonControlFrameType::TEXT; + $this->nonControlFrameType = $config['nonControlFrameType'] ?? NonControlFrameType::Text; } /** @@ -76,7 +76,7 @@ protected function bindEvents(): void try { // @phpstan-ignore-next-line - $connection->websocketType = NonControlFrameType::TEXT === $this->nonControlFrameType ? Websocket::BINARY_TYPE_BLOB : Websocket::BINARY_TYPE_ARRAYBUFFER; + $connection->websocketType = NonControlFrameType::Text === $this->nonControlFrameType ? Websocket::BINARY_TYPE_BLOB : Websocket::BINARY_TYPE_ARRAYBUFFER; $clientId = $connection->id; $worker = $this->worker; $request = new WorkermanRequest($worker, $connection, new Request($httpHeader), 'ws'); @@ -172,7 +172,7 @@ public function push(int|string $clientId, string $data, int $opcode = 1): bool /** * {@inheritDoc} */ - public function getNonControlFrameType(): int + public function getNonControlFrameType(): NonControlFrameType { return $this->nonControlFrameType; } diff --git a/src/Components/workerman/tests/unit/AppServer/config/config.php b/src/Components/workerman/tests/unit/AppServer/config/config.php index 038835c406..ebbd5ccc97 100644 --- a/src/Components/workerman/tests/unit/AppServer/config/config.php +++ b/src/Components/workerman/tests/unit/AppServer/config/config.php @@ -83,7 +83,7 @@ 'host' => env('SERVER_HOST', '127.0.0.1'), 'port' => 13002, 'shareWorker' => 'http', - 'nonControlFrameType' => NonControlFrameType::BINARY, + 'nonControlFrameType' => NonControlFrameType::Binary, 'configs' => [ ], ], diff --git a/src/Cron/Annotation/Cron.php b/src/Cron/Annotation/Cron.php index 6b670f1634..a7cd271cf7 100644 --- a/src/Cron/Annotation/Cron.php +++ b/src/Cron/Annotation/Cron.php @@ -5,6 +5,7 @@ namespace Imi\Cron\Annotation; use Imi\Bean\Annotation\Base; +use Imi\Cron\Consts\UniqueLevel; /** * 定时任务注解. @@ -62,7 +63,7 @@ public function __construct( /** * 定时任务唯一性设置;当前实例唯一: current;所有实例唯一: all;不唯一: null. */ - public ?string $unique = null, + public ?UniqueLevel $unique = null, /** * 用于锁的 `Redis` 连接池名. */ diff --git a/src/Cron/Consts/CronTaskType.php b/src/Cron/Consts/CronTaskType.php index 05f9d57159..6a34ea0ed2 100644 --- a/src/Cron/Consts/CronTaskType.php +++ b/src/Cron/Consts/CronTaskType.php @@ -4,16 +4,12 @@ namespace Imi\Cron\Consts; -use Imi\Enum\Annotation\EnumItem; -use Imi\Enum\BaseEnum; - /** * 定时任务类型. */ -class CronTaskType extends BaseEnum +class CronTaskType { use \Imi\Util\Traits\TStaticClass; - #[EnumItem(text: '定时任务进程')] public const CRON_PROCESS = 'cron_process'; } diff --git a/src/Cron/Consts/UniqueLevel.php b/src/Cron/Consts/UniqueLevel.php index 85345a012b..0e323a5541 100644 --- a/src/Cron/Consts/UniqueLevel.php +++ b/src/Cron/Consts/UniqueLevel.php @@ -4,19 +4,18 @@ namespace Imi\Cron\Consts; -use Imi\Enum\Annotation\EnumItem; -use Imi\Enum\BaseEnum; - /** * 任务唯一性等级. */ -class UniqueLevel extends BaseEnum +enum UniqueLevel: string { - use \Imi\Util\Traits\TStaticClass; - - #[EnumItem(text: '当前实例唯一')] - public const CURRENT = 'current'; + /** + * 当前实例唯一 + */ + case Current = 'current'; - #[EnumItem(text: '所有实例唯一')] - public const ALL = 'all'; + /** + * 所有实例唯一 + */ + case All = 'all'; } diff --git a/src/Cron/Contract/ICronManager.php b/src/Cron/Contract/ICronManager.php index dd1196accb..ebd88aa69c 100644 --- a/src/Cron/Contract/ICronManager.php +++ b/src/Cron/Contract/ICronManager.php @@ -5,6 +5,7 @@ namespace Imi\Cron\Contract; use Imi\Cron\Annotation\Cron; +use Imi\Cron\Consts\UniqueLevel; use Imi\Cron\CronTask; /** @@ -20,7 +21,7 @@ public function addCronByAnnotation(Cron $cron, string $pointClass): void; /** * 增加定时任务 */ - public function addCron(string $id, ?string $type, callable|string $task, array $cronRules, mixed $data, float $lockExpire = 3, ?string $unique = null, ?string $redisPool = null, float $lockWaitTimeout = 3, bool $force = false): void; + public function addCron(string $id, ?string $type, callable|string $task, array $cronRules, mixed $data, float $lockExpire = 3, ?UniqueLevel $unique = null, ?string $redisPool = null, float $lockWaitTimeout = 3, bool $force = false): void; /** * 移除定时任务 diff --git a/src/Cron/CronLock.php b/src/Cron/CronLock.php index bcf8499d67..a8ea889124 100644 --- a/src/Cron/CronLock.php +++ b/src/Cron/CronLock.php @@ -42,10 +42,10 @@ public function lock(CronTask $task): bool { case null: return $this->noLocks[$id] = true; - case UniqueLevel::ALL: + case UniqueLevel::All: $keyPrefix = 'imi:cron:lock:unique:all:'; break; - case UniqueLevel::CURRENT: + case UniqueLevel::Current: $keyPrefix = 'imi:cron:lock:unique:' . App::get(ProcessAppContexts::MASTER_PID) . ':'; break; default: diff --git a/src/Cron/CronManager.php b/src/Cron/CronManager.php index 1c862003ec..8e8f071f15 100644 --- a/src/Cron/CronManager.php +++ b/src/Cron/CronManager.php @@ -9,6 +9,7 @@ use Imi\Cli\ImiCommand; use Imi\Cron\Annotation\Cron; use Imi\Cron\Consts\CronTaskType; +use Imi\Cron\Consts\UniqueLevel; use Imi\Cron\Contract\ICronManager; use Imi\Cron\Contract\ICronTask; use Imi\Util\Process\ProcessAppContexts; @@ -85,7 +86,7 @@ public function addCronByAnnotation(Cron $cron, string $pointClass): void /** * {@inheritDoc} */ - public function addCron(string $id, ?string $type, callable|string $task, array $cronRules, mixed $data, float $lockExpire = 3, ?string $unique = null, ?string $redisPool = null, float $lockWaitTimeout = 3, bool $force = false, bool $successLog = true): void + public function addCron(string $id, ?string $type, callable|string $task, array $cronRules, mixed $data, float $lockExpire = 3, ?UniqueLevel $unique = null, ?string $redisPool = null, float $lockWaitTimeout = 3, bool $force = false, bool $successLog = true): void { if (isset($this->tasks[$id])) { diff --git a/src/Cron/CronTask.php b/src/Cron/CronTask.php index 30383d08e8..72f0f38343 100644 --- a/src/Cron/CronTask.php +++ b/src/Cron/CronTask.php @@ -7,6 +7,8 @@ /** * 定时任务对象 */ +use Imi\Cron\Consts\UniqueLevel; + class CronTask { /** @@ -51,12 +53,9 @@ public function __construct( */ private readonly float $maxExecutionTime = 3, /** - * 定时任务唯一性设置 - * 当前实例唯一: current - * 所有实例唯一: all - * 不唯一: null. + * 定时任务唯一性设置. */ - private readonly ?string $unique = null, + private readonly ?UniqueLevel $unique = null, /** * 用于锁的 `Redis` 连接池名. */ @@ -139,7 +138,7 @@ public function getData(): mixed /** * Get 在当前服务实例中唯一,只能同时执行一个. */ - public function getUnique(): ?string + public function getUnique(): ?UniqueLevel { return $this->unique; } diff --git a/src/Db/Mysql/Consts/LogicalOperator.php b/src/Db/Mysql/Consts/LogicalOperator.php index 5f7886bb93..7deed8bfb4 100644 --- a/src/Db/Mysql/Consts/LogicalOperator.php +++ b/src/Db/Mysql/Consts/LogicalOperator.php @@ -4,28 +4,31 @@ namespace Imi\Db\Mysql\Consts; -use Imi\Enum\Annotation\EnumItem; -use Imi\Enum\BaseEnum; - -class LogicalOperator extends BaseEnum +class LogicalOperator { use \Imi\Util\Traits\TStaticClass; - #[EnumItem] public const AND = 'and'; - #[EnumItem] public const OR = 'or'; - #[EnumItem] public const XOR = 'xor'; - #[EnumItem] public const AND_NOT = 'and not'; - #[EnumItem] public const OR_NOT = 'or not'; - #[EnumItem] public const XOR_NOT = 'xor not'; + + public static function values(): array + { + return [ + static::AND, + static::OR, + static::XOR, + static::AND_NOT, + static::OR_NOT, + static::XOR_NOT, + ]; + } } diff --git a/src/Db/Mysql/Query/FullText/SearchModifier.php b/src/Db/Mysql/Query/FullText/SearchModifier.php index 9ecd86f397..e4d0f33687 100644 --- a/src/Db/Mysql/Query/FullText/SearchModifier.php +++ b/src/Db/Mysql/Query/FullText/SearchModifier.php @@ -4,25 +4,28 @@ namespace Imi\Db\Mysql\Query\FullText; -use Imi\Enum\Annotation\EnumItem; -use Imi\Enum\BaseEnum; - /** * 搜索修饰符. */ -class SearchModifier extends BaseEnum +class SearchModifier { - use \Imi\Util\Traits\TStaticClass; - - #[EnumItem(text: '自然语言模式')] + /** + * 自然语言模式. + */ public const IN_NATURAL_LANGUAGE_MODE = 'IN NATURAL LANGUAGE MODE'; - #[EnumItem(text: '自然语言模式,带查询扩展')] + /** + * 自然语言模式,带查询扩展. + */ public const IN_NATURAL_LANGUAGE_MODE_WITH_QUERY_EXPANSION = 'IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION'; - #[EnumItem(text: '布尔模式')] + /** + * 布尔模式. + */ public const IN_BOOLEAN_MODE = 'IN BOOLEAN MODE'; - #[EnumItem(text: '带查询扩展')] + /** + * 带查询扩展. + */ public const WITH_QUERY_EXPANSION = 'WITH QUERY EXPANSION'; } diff --git a/src/Db/Query/Traits/TWhereCollector.php b/src/Db/Query/Traits/TWhereCollector.php index 28235739ae..7c71aeaf62 100644 --- a/src/Db/Query/Traits/TWhereCollector.php +++ b/src/Db/Query/Traits/TWhereCollector.php @@ -149,7 +149,12 @@ protected function parseWhereEx(array $condition): array $result = []; foreach ($condition as $key => $value) { - if (null === LogicalOperator::getText(strtolower($key))) + if (\in_array(strtolower($key), LogicalOperator::values())) + { + // 逻辑运算符 + $result[] = new WhereBrackets(fn () => $this->parseWhereEx($value), $key); + } + else { // 条件 k => v if (\is_array($value)) @@ -195,11 +200,6 @@ protected function parseWhereEx(array $condition): array $result[] = new Where($key, '=', $value); } } - else - { - // 逻辑运算符 - $result[] = new WhereBrackets(fn () => $this->parseWhereEx($value), $key); - } } return $result; diff --git a/src/Model/IdGenerator/UUIDGenerator.php b/src/Model/IdGenerator/UUIDGenerator.php index 78f47de143..055695b483 100644 --- a/src/Model/IdGenerator/UUIDGenerator.php +++ b/src/Model/IdGenerator/UUIDGenerator.php @@ -9,17 +9,20 @@ class UUIDGenerator implements IIdGenerator { + /** + * @param array{type?: UUIDGeneratorType, ns?: string, nsField?: string, name?: string, nameField?: string} $options + */ public function generate(?BaseModel $model, array $options = []): mixed { - switch ($type = $options['type'] ?? UUIDGeneratorType::RANDOM) + switch ($type = $options['type'] ?? UUIDGeneratorType::Random) { - case UUIDGeneratorType::TIME: + case UUIDGeneratorType::Time: return uuid_create(UUID_TYPE_TIME); - case UUIDGeneratorType::RANDOM: + case UUIDGeneratorType::Random: return uuid_create(UUID_TYPE_RANDOM); case UUIDGeneratorType::MD5: case UUIDGeneratorType::SHA1: - $functionName = 'uuid_generate_' . $type; + $functionName = 'uuid_generate_' . $type->name; if (isset($options['ns'])) { $ns = $options['ns']; @@ -44,7 +47,7 @@ public function generate(?BaseModel $model, array $options = []): mixed return $functionName($ns, $name); default: - throw new \InvalidArgumentException(sprintf('Invalid value %s in enum %s', $type, static::class)); + throw new \InvalidArgumentException(sprintf('Invalid value %s in enum %s', $type->name, static::class)); } } } diff --git a/src/Model/IdGenerator/UUIDGeneratorType.php b/src/Model/IdGenerator/UUIDGeneratorType.php index 12e8e5d5ad..ea721f5422 100644 --- a/src/Model/IdGenerator/UUIDGeneratorType.php +++ b/src/Model/IdGenerator/UUIDGeneratorType.php @@ -4,20 +4,16 @@ namespace Imi\Model\IdGenerator; -use Imi\Enum\BaseEnum; - /** * UUID 生成器类型. */ -class UUIDGeneratorType extends BaseEnum +enum UUIDGeneratorType { - use \Imi\Util\Traits\TStaticClass; - - public const TIME = 'time'; + case Time; - public const RANDOM = 'random'; + case Random; - public const MD5 = 'md5'; + case MD5; - public const SHA1 = 'sha1'; + case SHA1; } diff --git a/src/Server/WebSocket/Contract/IWebSocketServer.php b/src/Server/WebSocket/Contract/IWebSocketServer.php index a501d12c15..3d5165521b 100644 --- a/src/Server/WebSocket/Contract/IWebSocketServer.php +++ b/src/Server/WebSocket/Contract/IWebSocketServer.php @@ -6,6 +6,7 @@ use Imi\Server\Contract\IServer; use Imi\Server\Group\Contract\IServerGroup; +use Imi\Server\WebSocket\Enum\NonControlFrameType; interface IWebSocketServer extends IServer, IServerGroup { @@ -17,5 +18,5 @@ public function push(int|string $clientId, string $data, int $opcode = 1): bool; /** * 非控制帧类型. */ - public function getNonControlFrameType(): int; + public function getNonControlFrameType(): NonControlFrameType; } diff --git a/src/Server/WebSocket/Dispatcher.php b/src/Server/WebSocket/Dispatcher.php index 853ab8b0c0..35234083be 100644 --- a/src/Server/WebSocket/Dispatcher.php +++ b/src/Server/WebSocket/Dispatcher.php @@ -33,7 +33,7 @@ public function dispatch(IFrame $frame): void { /** @var IWebSocketServer $server */ $server = RequestContext::getServer(); - $server->push($frame->getClientId(), $server->getBean(DataParser::class)->encode($responseData), $server->getNonControlFrameType()); + $server->push($frame->getClientId(), $server->getBean(DataParser::class)->encode($responseData), $server->getNonControlFrameType()->value); } } diff --git a/src/Server/WebSocket/Enum/NonControlFrameType.php b/src/Server/WebSocket/Enum/NonControlFrameType.php index 08944f205d..d6d387b53b 100644 --- a/src/Server/WebSocket/Enum/NonControlFrameType.php +++ b/src/Server/WebSocket/Enum/NonControlFrameType.php @@ -4,19 +4,18 @@ namespace Imi\Server\WebSocket\Enum; -use Imi\Enum\Annotation\EnumItem; -use Imi\Enum\BaseEnum; - /** * Websocket 非控制帧类型. */ -class NonControlFrameType extends BaseEnum +enum NonControlFrameType: int { - use \Imi\Util\Traits\TStaticClass; - - #[EnumItem(text: '文本帧')] - public const TEXT = 1; + /** + * 文本帧. + */ + case Text = 1; - #[EnumItem(text: '二进制帧')] - public const BINARY = 2; + /** + * 二进制帧. + */ + case Binary = 2; } diff --git a/src/Util/EnumUtil.php b/src/Util/EnumUtil.php new file mode 100644 index 0000000000..33600aa021 --- /dev/null +++ b/src/Util/EnumUtil.php @@ -0,0 +1,48 @@ +name === $case) + { + return $c; + } + } + + return null; + } + + public static function in(string $enum, mixed $value): bool + { + foreach ($enum::cases() as $case) + { + if ($case === $value || ($case->value ?? $case->name) === $value) + { + return true; + } + } + + return false; + } +} diff --git a/src/Validate/ValidatorHelper.php b/src/Validate/ValidatorHelper.php index 47c734069b..5101afea65 100644 --- a/src/Validate/ValidatorHelper.php +++ b/src/Validate/ValidatorHelper.php @@ -4,7 +4,7 @@ namespace Imi\Validate; -use Imi\Enum\BaseEnum; +use Imi\Util\EnumUtil; /** * 验证器工具类. @@ -319,22 +319,25 @@ public static function notIn(mixed $value, string|array $list): bool /** * 值在枚举值范围内. - * - * @param class-string $enumClass */ public static function inEnum(mixed $value, string $enumClass): bool { - return \in_array($value, $enumClass::getValues()); + if (is_subclass_of($enumClass, \UnitEnum::class)) + { + return EnumUtil::in($enumClass, $value); + } + else + { + return \in_array($value, $enumClass::getValues()); + } } /** * 值不在枚举值范围内. - * - * @param class-string $enumClass */ public static function notInEnum(mixed $value, string $enumClass): bool { - return !\in_array($value, $enumClass::getValues()); + return !static::inEnum($value, $enumClass); } /** diff --git a/tests/unit/Component/Bean/EnumBean.php b/tests/unit/Component/Bean/EnumBean.php new file mode 100644 index 0000000000..86e08b1424 --- /dev/null +++ b/tests/unit/Component/Bean/EnumBean.php @@ -0,0 +1,38 @@ +enum1; + } + + public function getEnum2(): TestEnumBeanBacked + { + return $this->enum2; + } + + public function getEnum3(): TestEnumBean|TestEnumBeanBacked + { + return $this->enum3; + } +} diff --git a/tests/unit/Component/Enum/TestEnumBean.php b/tests/unit/Component/Enum/TestEnumBean.php new file mode 100644 index 0000000000..2900cbfa15 --- /dev/null +++ b/tests/unit/Component/Enum/TestEnumBean.php @@ -0,0 +1,11 @@ + 'sha1', 'ns' => '99e4edaf-8363-466e-bddf-7254db57675c', 'nameField' => 'title'])] + #[Id(index: false, generator: 'Imi\\Model\\IdGenerator\\UUIDGenerator', generatorOptions: ['type' => UUIDGeneratorType::SHA1, 'ns' => '99e4edaf-8363-466e-bddf-7254db57675c', 'nameField' => 'title'])] protected ?string $content = null; /** diff --git a/tests/unit/Component/Tests/BeanTest.php b/tests/unit/Component/Tests/BeanTest.php index ed114394e4..3b402c6596 100644 --- a/tests/unit/Component/Tests/BeanTest.php +++ b/tests/unit/Component/Tests/BeanTest.php @@ -11,6 +11,8 @@ use Imi\Test\Component\Bean\BeanA; use Imi\Test\Component\Bean\BeanB; use Imi\Test\Component\Bean\BeanC; +use Imi\Test\Component\Enum\TestEnumBean; +use Imi\Test\Component\Enum\TestEnumBeanBacked; use Imi\Util\Imi; /** @@ -386,6 +388,33 @@ public function testReadOnlyBean(): void $this->assertEquals('ReadOnlyBean', $bean->test()); } + public function testEnumBean(): void + { + /** @var \Imi\Test\Component\Bean\EnumBean $bean */ + // @phpstan-ignore-next-line + $bean = App::getBean('EnumBean1'); + // @phpstan-ignore-next-line + $this->assertInstanceOf(\Imi\Test\Component\Bean\EnumBean::class, $bean); + // @phpstan-ignore-next-line + $this->assertEquals(TestEnumBean::A, $bean->getEnum1()); + // @phpstan-ignore-next-line + $this->assertEquals(TestEnumBeanBacked::B, $bean->getEnum2()); + // @phpstan-ignore-next-line + $this->assertEquals(TestEnumBean::A, $bean->getEnum3()); + + /** @var \Imi\Test\Component\Bean\EnumBean $bean */ + // @phpstan-ignore-next-line + $bean = App::getBean('EnumBean2'); + // @phpstan-ignore-next-line + $this->assertInstanceOf(\Imi\Test\Component\Bean\EnumBean::class, $bean); + // @phpstan-ignore-next-line + $this->assertEquals(TestEnumBean::B, $bean->getEnum1()); + // @phpstan-ignore-next-line + $this->assertEquals(TestEnumBeanBacked::A, $bean->getEnum2()); + // @phpstan-ignore-next-line + $this->assertEquals(TestEnumBeanBacked::B, $bean->getEnum3()); + } + // @phpstan-ignore-next-line private function test1(): self { diff --git a/tests/unit/Component/Tests/Util/EnumTest.php b/tests/unit/Component/Tests/Util/EnumTest.php new file mode 100644 index 0000000000..4e875a295a --- /dev/null +++ b/tests/unit/Component/Tests/Util/EnumTest.php @@ -0,0 +1,37 @@ +assertEquals(TestEnumBean::A, EnumUtil::fromName(TestEnumBean::class, 'A')); + $this->expectException(\ValueError::class); + EnumUtil::fromName(TestEnumBean::class, 'ABC'); + } + + public function testTryFromName(): void + { + $this->assertEquals(TestEnumBean::A, EnumUtil::tryFromName(TestEnumBean::class, 'A')); + $this->assertNull(EnumUtil::tryFromName(TestEnumBean::class, 'ABC')); + } + + public function testIn(): void + { + $this->assertTrue(EnumUtil::in(TestEnumBean::class, 'A')); + $this->assertTrue(EnumUtil::in(TestEnumBean::class, TestEnumBean::A)); + $this->assertFalse(EnumUtil::in(TestEnumBean::class, 'ABC')); + + $this->assertTrue(EnumUtil::in(TestEnumBeanBacked::class, 'hello')); + $this->assertTrue(EnumUtil::in(TestEnumBeanBacked::class, TestEnumBeanBacked::A)); + $this->assertFalse(EnumUtil::in(TestEnumBeanBacked::class, 'hello imi')); + } +} diff --git a/tests/unit/Component/Tests/ValidatorHelperTest.php b/tests/unit/Component/Tests/ValidatorHelperTest.php index 35eda68a26..831485af63 100644 --- a/tests/unit/Component/Tests/ValidatorHelperTest.php +++ b/tests/unit/Component/Tests/ValidatorHelperTest.php @@ -6,6 +6,8 @@ use Imi\Test\BaseTest; use Imi\Test\Component\Enum\TestEnum; +use Imi\Test\Component\Enum\TestEnumBean; +use Imi\Test\Component\Enum\TestEnumBeanBacked; use Imi\Validate\ValidatorHelper; use PHPUnit\Framework\Assert; @@ -349,12 +351,24 @@ public function testInEnum(): void { Assert::assertTrue(ValidatorHelper::inEnum(TestEnum::A, TestEnum::class)); Assert::assertFalse(ValidatorHelper::inEnum(4, TestEnum::class)); + Assert::assertTrue(ValidatorHelper::inEnum(TestEnumBean::A, TestEnumBean::class)); + Assert::assertTrue(ValidatorHelper::inEnum('A', TestEnumBean::class)); + Assert::assertFalse(ValidatorHelper::inEnum(4, TestEnumBean::class)); + Assert::assertTrue(ValidatorHelper::inEnum(TestEnumBeanBacked::A, TestEnumBeanBacked::class)); + Assert::assertTrue(ValidatorHelper::inEnum('hello', TestEnumBeanBacked::class)); + Assert::assertFalse(ValidatorHelper::inEnum(4, TestEnumBeanBacked::class)); } public function testNotInEnum(): void { Assert::assertTrue(ValidatorHelper::notInEnum(4, TestEnum::class)); Assert::assertFalse(ValidatorHelper::notInEnum(TestEnum::A, TestEnum::class)); + Assert::assertTrue(ValidatorHelper::notInEnum(4, TestEnumBean::class)); + Assert::assertFalse(ValidatorHelper::notInEnum(TestEnumBean::A, TestEnumBean::class)); + Assert::assertFalse(ValidatorHelper::notInEnum('A', TestEnumBean::class)); + Assert::assertTrue(ValidatorHelper::notInEnum(4, TestEnumBeanBacked::class)); + Assert::assertFalse(ValidatorHelper::notInEnum(TestEnumBeanBacked::A, TestEnumBeanBacked::class)); + Assert::assertFalse(ValidatorHelper::notInEnum('hello', TestEnumBeanBacked::class)); } public function testCnIdcard(): void diff --git a/tests/unit/Component/config/config.php b/tests/unit/Component/config/config.php index af2aefeff7..555c7a8ee9 100644 --- a/tests/unit/Component/config/config.php +++ b/tests/unit/Component/config/config.php @@ -88,6 +88,16 @@ 'DbQueryLog' => [ 'enable' => true, ], + 'EnumBean1' => [ + 'enum1' => 'A', + 'enum2' => 'imi', + 'enum3' => 'A', + ], + 'EnumBean2' => [ + 'enum1' => 'B', + 'enum2' => 'hello', + 'enum3' => 'imi', + ], ], 'imi-framework' => 'very six', From 8199a599ec559ec66fb83ec07450bdada1636485 Mon Sep 17 00:00:00 2001 From: Yurun Date: Wed, 15 Nov 2023 13:23:16 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E5=BC=BA=E7=B1=BB=E5=9E=8B=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E6=B3=A8=E9=87=8A=E7=B1=BB=E5=9E=8B=EF=BC=8C=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E6=9C=AA=E5=AE=89=E8=A3=85=E5=AF=B9=E5=BA=94=E6=89=A9?= =?UTF-8?q?=E5=B1=95=E8=BF=90=E8=A1=8C=E6=97=B6=E6=8A=A5=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E9=94=99=E8=AF=AF=20(#649)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/pgsql/src/Db/Drivers/Swoole/Driver.php | 4 ++-- src/Components/pgsql/src/Db/Drivers/SwooleNew/Driver.php | 4 ++-- src/Db/Drivers/TPdoDriver.php | 4 ++-- src/Db/Mysql/Drivers/Mysqli/Driver.php | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Components/pgsql/src/Db/Drivers/Swoole/Driver.php b/src/Components/pgsql/src/Db/Drivers/Swoole/Driver.php index 89cd7650a6..3fb90639fd 100644 --- a/src/Components/pgsql/src/Db/Drivers/Swoole/Driver.php +++ b/src/Components/pgsql/src/Db/Drivers/Swoole/Driver.php @@ -169,9 +169,9 @@ public function close(): void } /** - * {@inheritDoc} + * @return PostgreSQL */ - public function getInstance(): PostgreSQL + public function getInstance(): object { return $this->instance; } diff --git a/src/Components/pgsql/src/Db/Drivers/SwooleNew/Driver.php b/src/Components/pgsql/src/Db/Drivers/SwooleNew/Driver.php index a5fa3dc420..845654e7d7 100644 --- a/src/Components/pgsql/src/Db/Drivers/SwooleNew/Driver.php +++ b/src/Components/pgsql/src/Db/Drivers/SwooleNew/Driver.php @@ -162,9 +162,9 @@ public function close(): void } /** - * {@inheritDoc} + * @return PostgreSQL */ - public function getInstance(): PostgreSQL + public function getInstance(): object { return $this->instance; } diff --git a/src/Db/Drivers/TPdoDriver.php b/src/Db/Drivers/TPdoDriver.php index dfafff8ae4..3d08f1ff0d 100644 --- a/src/Db/Drivers/TPdoDriver.php +++ b/src/Db/Drivers/TPdoDriver.php @@ -135,9 +135,9 @@ public function close(): void } /** - * {@inheritDoc} + * @return \PDO */ - public function getInstance(): \PDO + public function getInstance(): object { return $this->instance; } diff --git a/src/Db/Mysql/Drivers/Mysqli/Driver.php b/src/Db/Mysql/Drivers/Mysqli/Driver.php index 9d514666c6..5344e1af68 100644 --- a/src/Db/Mysql/Drivers/Mysqli/Driver.php +++ b/src/Db/Mysql/Drivers/Mysqli/Driver.php @@ -137,9 +137,9 @@ public function close(): void } /** - * {@inheritDoc} + * @return \mysqli */ - public function getInstance(): \mysqli + public function getInstance(): object { return $this->instance; } From 3a9aeb76581a324ae78c55239ed4757fc6774dbe Mon Sep 17 00:00:00 2001 From: zxin <14545600+NHZEX@users.noreply.github.com> Date: Mon, 20 Nov 2023 11:21:24 +0800 Subject: [PATCH 8/9] =?UTF-8?q?[3.0]=20=E5=85=A8=E5=B1=80=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E5=A4=84=E7=90=86=E5=A2=9E=E5=BC=BA=20(#651)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update: 支持设置全局错误&异常处理器 * Update: 更新文档 * Update: 更新文档 --- doc/SUMMARY.md | 2 +- doc/core/handleError.md | 57 ++++++++++++++++++++++++++- src/Log/AbstractErrorEventHandler.php | 26 ++++++++++++ src/Log/ErrorLog.php | 44 +++++++++++++++++---- src/Log/IErrorEventHandler.php | 19 +++++++++ 5 files changed, 138 insertions(+), 10 deletions(-) create mode 100644 src/Log/AbstractErrorEventHandler.php create mode 100644 src/Log/IErrorEventHandler.php diff --git a/doc/SUMMARY.md b/doc/SUMMARY.md index 6415419507..59ac489391 100644 --- a/doc/SUMMARY.md +++ b/doc/SUMMARY.md @@ -28,7 +28,7 @@ * [事件监听](components/event/index.md) * [事件列表](core/events.md) * [中间件](core/middleware.md) -* [错误转为异常捕获](core/handleError.md) +* [全局异常处理](core/handleError.md) * [内部进程间通讯](core/processCommunication.md) * [Server 对象](core/server.md) * [长连接分布式解决方案](core/long-connection-distributed.md) diff --git a/doc/core/handleError.md b/doc/core/handleError.md index 7e78d29ebf..29ece7b8e8 100644 --- a/doc/core/handleError.md +++ b/doc/core/handleError.md @@ -1,8 +1,8 @@ -# 错误转为异常捕获 +# 全局异常处理 [toc] -imi 框架底层支持将错误转为异常,可以通过 `try...catch` 来捕获。 +## 异常处理器配置 在 `config.php` 中的 `beans` 配置 @@ -16,10 +16,63 @@ imi 框架底层支持将错误转为异常,可以通过 `try...catch` 来捕 'catchLevel' => E_ALL | E_STRICT, // 抛出异常的错误级别,除此之外全部记录日志,此为默认值 'exceptionLevel' => E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR | E_WARNING | E_CORE_WARNING | E_COMPILE_WARNING | E_USER_WARNING, + /** + * 异常事件处理器数组 + * @var array> + */ + 'errorEventHandlers' => []; ], ] ``` +## 错误转为异常捕获 + +imi 框架底层支持将错误转为异常(通过`catchLevel`选项控制),可以通过 `try...catch` 来捕获。 + > 错误级别参考: 抛出的异常类为 `\ErrorException` + +## 全局异常处理器 + +支持通过`errorEventHandlers`数组声明多个全局异常事件处理器,每个异常处理器必须继承`Imi\Log\AbsErrorEventHandler`,并实现`handleError`,`handleException`方法。 +多个异常处理器将按顺序执行,可调用方法`stopPropagation`取消后续异常处理器执行并阻止系统默认的异常处理。 + +> 请务必确保异常处理器内不要再次抛出异常,做好异常捕获安全处理。 + +### Demo + +```php +# 当 catchLevel 设置为 E_ALL 时,添加以下处理器配合处理错误通知 + +stopPropagation(); + + Log::log(LogLevel::INFO, $errStr); + } + } + + public function handleException(\Throwable $throwable): void + { + // 可以处理更多异常状况... + } +} + +``` + diff --git a/src/Log/AbstractErrorEventHandler.php b/src/Log/AbstractErrorEventHandler.php new file mode 100644 index 0000000000..a5fca0dfcd --- /dev/null +++ b/src/Log/AbstractErrorEventHandler.php @@ -0,0 +1,26 @@ +stopPropagation; + } + + /** + * 取消系统内部的错误域异常处理并停止后续处理器执行. + */ + public function stopPropagation(bool $stop = true): void + { + $this->stopPropagation = $stop; + } +} diff --git a/src/Log/ErrorLog.php b/src/Log/ErrorLog.php index 4150d3a7b3..d88c830516 100644 --- a/src/Log/ErrorLog.php +++ b/src/Log/ErrorLog.php @@ -27,6 +27,13 @@ class ErrorLog */ protected int $exceptionLevel = \E_ERROR | \E_PARSE | \E_CORE_ERROR | \E_COMPILE_ERROR | \E_USER_ERROR | \E_RECOVERABLE_ERROR | \E_WARNING | \E_CORE_WARNING | \E_COMPILE_WARNING | \E_USER_WARNING; + /** + * 异常事件处理器. + * + * @var array> + */ + protected array $errorEventHandlers = []; + /** * 注册错误监听. */ @@ -36,7 +43,7 @@ public function register(): void register_shutdown_function([$this, 'onShutdown']); // @phpstan-ignore-next-line set_error_handler($this->onError(...), $this->catchLevel); - set_exception_handler(static fn (\Throwable $th) => Log::error($th)); + set_exception_handler($this->onException(...)); } /** @@ -44,18 +51,41 @@ public function register(): void */ public function onError(int $errno, string $errstr, string $errfile, int $errline): void { + foreach ($this->errorEventHandlers as $class) + { + $handler = new $class(); + $handler->handleError($errno, $errstr, $errfile, $errline); + if ($handler->isPropagationStopped()) + { + return; + } + } if ($this->exceptionLevel & $errno) { throw new \ErrorException($errstr, 0, $errno, $errfile, $errline); } - $method = match ($errno) + $level = match ($errno) { - \E_ERROR, \E_PARSE, \E_CORE_ERROR, \E_COMPILE_ERROR, \E_USER_ERROR, \E_RECOVERABLE_ERROR => 'error', - \E_WARNING, \E_CORE_WARNING, \E_COMPILE_WARNING, \E_USER_WARNING => 'warning', - \E_NOTICE, \E_USER_NOTICE => 'notice', - default => 'info', + \E_ERROR, \E_PARSE, \E_CORE_ERROR, \E_COMPILE_ERROR, \E_USER_ERROR, \E_RECOVERABLE_ERROR => \Psr\Log\LogLevel::ERROR, + \E_WARNING, \E_CORE_WARNING, \E_COMPILE_WARNING, \E_USER_WARNING => \Psr\Log\LogLevel::WARNING, + \E_NOTICE, \E_USER_NOTICE => \Psr\Log\LogLevel::NOTICE, + default => \Psr\Log\LogLevel::INFO, }; - Log::$method($errstr); + Log::log($level, $errstr); + } + + public function onException(\Throwable $throwable): void + { + foreach ($this->errorEventHandlers as $class) + { + $handler = new $class(); + $handler->handleException($throwable); + if ($handler->isPropagationStopped()) + { + return; + } + } + Log::error($throwable); } /** diff --git a/src/Log/IErrorEventHandler.php b/src/Log/IErrorEventHandler.php new file mode 100644 index 0000000000..4d3b587ec1 --- /dev/null +++ b/src/Log/IErrorEventHandler.php @@ -0,0 +1,19 @@ + Date: Fri, 24 Nov 2023 17:04:54 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20phpstan=20=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=20(#653)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Model/BaseModel.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Model/BaseModel.php b/src/Model/BaseModel.php index 38a1c49902..3209819c39 100644 --- a/src/Model/BaseModel.php +++ b/src/Model/BaseModel.php @@ -396,9 +396,11 @@ public function toArray(): array { continue; } + // @phpstan-ignore-next-line if (\in_array($name, $relationFieldNames ??= ($meta->hasRelation() ? ModelRelationManager::getRelationFieldNames($this) : []))) { /** @var AutoSelect|null $autoSelect */ + // @phpstan-ignore-next-line $autoSelect = AnnotationManager::getPropertyAnnotations($realClass ??= ($this->__realClass ??= $meta->getRealModelClass()), $name, AutoSelect::class, true, true); if ($autoSelect && !$autoSelect->alwaysShow) {