Compare commits

...

71 Commits

Author SHA1 Message Date
李东云
7d12733013 test(email): 将测试发件邮箱改为了 exchange
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-08-29 15:09:34 +08:00
李东云
68ed42b576 build(composer): 添加 hyperf 官方 pest 组件
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-08-29 15:08:53 +08:00
李东云
3042ce0054 chore(release): 1.0.0-alpha.2 2023-07-21 08:22:48 +00:00
李东云
b30c84488b fix(controller): 修复方法访问级别不足以继承的问题
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-07-21 16:22:36 +08:00
李东云
c262d38ad0 chore(release): 1.0.0-alpha.1 2023-07-21 03:39:01 +00:00
李东云
a8ec7d8255 build(composer): 更新依赖
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-07-21 11:38:31 +08:00
李东云
f1948ab0fe build(release): 增加 alpha 标识,准备正式版
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-07-21 11:04:39 +08:00
李东云
ae8001a595 chore(release): 1.0.0-alpha.0 2023-07-21 03:01:22 +00:00
李东云
68844a6132 feat(controller): 增加了一个 Rest 风格的 trait
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-07-21 10:55:10 +08:00
李东云
fd788a7eb8 feat(trait): 增加了分页响应的统一处理方法
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-07-19 15:52:35 +08:00
李东云
7ccf36b398 docs(utils): 移除了导致编辑器出错的注解
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-07-07 10:31:31 +08:00
李东云
3d86b05fff chore(release): 0.2.23 2023-07-07 02:13:01 +00:00
李东云
722d124e1e fix(i18n): 修复获取偏好语言失败的问题
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-07-07 10:12:35 +08:00
李东云
5702e7f913 chore(release): 0.2.22 2023-07-06 09:54:58 +00:00
李东云
a6ec6951a9 fix(service): 修复 http 请求类中无效的 query
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-07-06 17:54:46 +08:00
李东云
a52fc28901 chore(release): 0.2.21 2023-07-05 08:41:23 +00:00
李东云
2b0374bcc8 chore(deprecated): 声明弃用了 SessionMiddleware
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-07-05 16:40:38 +08:00
李东云
8616c5f61c perf: 适配已弃用的命名空间
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-06-19 18:22:42 +08:00
李东云
aee67d78fc chore(release): 0.2.20 2023-06-19 10:15:18 +00:00
李东云
8974ee595b feat(handler): 增加了 restful 的支持
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-06-19 18:15:00 +08:00
李东云
205554068d chore(release): 0.2.19 2023-06-02 02:20:48 +00:00
李东云
648fe6c8f3 build(composer): 更新依赖
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-06-02 10:19:01 +08:00
李东云
c0aa128dd0 chore(release): 0.2.18 2023-06-02 02:12:27 +00:00
李东云
c748cbd3e3 build: 更新被弃用的写法
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-06-02 10:11:49 +08:00
李东云
43ebd0546a fix: 修复 http 请求失效的问题
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-06-02 10:05:09 +08:00
李东云
200a98293a chore(release): 0.2.17 2023-05-06 09:46:51 +00:00
李东云
be818b7080 feat(xml): 实现了解析xml的方法
Signed-off-by: 李东云 <dongyu.li@luxcreo.ai>
2023-05-06 17:46:32 +08:00
李东云
d22bd3ee58 build(composer): 更新依赖 2023-05-06 17:16:22 +08:00
李东云
0f9cae0288 chore(release): 0.2.16 2023-04-25 09:18:42 +00:00
李东云
0247dd415c feat(handler): 补全了各种错误的状态码 2023-04-25 17:18:10 +08:00
李东云
77f3141c56 fix(extend): 修复未传入 extends 不存在缺省值的问题 2023-04-25 17:04:57 +08:00
李东云
2a59a51f8b chore(release): 0.2.15 2023-04-13 15:38:50 +00:00
李东云
5e5792b28c feat: 默认绑定 CoreMiddleware 的映射关系 2023-04-13 23:38:38 +08:00
李东云
a6b71dbb03 fix(coreMiddleware): 修复restful 无法分页的问题 2023-04-13 23:37:18 +08:00
李东云
d836186296 chore(release): 0.2.14 2023-04-12 09:36:26 +00:00
李东云
e69c1494c3 feat(handler): 补充 restful 响应的状态码 2023-04-12 17:36:15 +08:00
李东云
11315aa109 chore(release): 0.2.13 2023-04-11 08:17:09 +00:00
李东云
90a521f90a feat(xml): 增加了 xml 生成的方法及测试用例 2023-04-11 16:16:49 +08:00
李东云
db31689f66 chore(release): 0.2.12 2023-04-10 07:00:53 +00:00
李东云
7e5cb89dfe build(composer): 更新依赖以兼容 nano 2023-04-10 15:00:34 +08:00
李东云
4ba0cb83f5 build(scripts): 更新脚本 2023-04-07 16:40:52 +08:00
李东云
c25e6eed52 build(phpstan): fix 2023-04-07 16:39:55 +08:00
ch4o5
2ee20984ce chore(release): 0.2.11 2023-04-03 10:36:37 +00:00
李东云
859a1a1f2a feat(i18n): 引入了 symfony 的 Accept-Language 机制 2023-04-03 18:36:07 +08:00
李东云
78b56a6aa9 build(composer): 更新依赖 2023-04-03 18:35:34 +08:00
李东云
c991c31260 build(composer): 更新依赖
限定了 hyperf/crontab 的版本,避开有问题的版本
2023-03-30 17:50:18 +08:00
ch4o5
1e4158639f chore(release): 0.2.10 2023-03-21 02:56:28 +00:00
李东云
70ad3078b1 build(composer): 更新依赖 2023-03-21 10:55:48 +08:00
李东云
afec642454 build(composer): 只留下了腾讯源,更新依赖 2023-03-20 11:27:50 +08:00
李东云
b2debf9c13 build(composer): 只留下了腾讯源,更新依赖 2023-03-20 10:11:27 +08:00
ch4o5
d7c902d697 chore(release): 0.2.9 2023-03-15 01:54:35 +00:00
李东云
de96e288c3 feat: 增加了inArray、hasExtends方法 2023-03-14 18:29:05 +08:00
李东云
7c1efe1a1f feat: 添加了 http 请求服务 2023-03-13 16:14:22 +08:00
李东云
e33c115938 feat: 增加默认api风格参数 2023-03-13 13:32:48 +08:00
李东云
b8c3d6d068 feat(api): 增加了可以使用中间件定制是否 restful 的逻辑 2023-03-13 11:00:16 +08:00
李东云
2d2148f3ec feat: 实现了通过中间件设置是否 restful 的逻辑 2023-03-10 18:29:41 +08:00
李东云
2d2a535fd2 fix: 修复了一处大小写错误 2023-03-08 17:37:27 +08:00
李东云
a618af5ab3 feat: 增加了对 session 中间件配置 cookie 方式的补充 2023-03-08 17:30:16 +08:00
ch4o5
28e0ceed11 chore(release): 0.2.8 2023-02-03 02:37:22 +00:00
李东云
c8f9b793ee fix(commonHandler): 修复了一处兼容问题 2023-02-03 10:30:32 +08:00
ch4o5
bf0dc896e4 chore(release): 0.2.7 2023-02-02 07:45:00 +00:00
李东云
a729270fac style(cs-fixer): prettier 2023-02-02 15:44:48 +08:00
李东云
099ab60103 fix(extend): 修复了解析不到为空不为数组的问题 2023-02-02 15:44:26 +08:00
李东云
e41847a234 test(extend): 补充测试用例 2023-02-01 21:11:13 +08:00
李东云
9026a3e0f0 Merge branch '0.2.x' into develop 2023-01-16 22:34:23 +08:00
李东云
135db1bf6a docs(README): 修复一直报错的文件名 2023-01-16 22:30:01 +08:00
李东云
5151787982 feat(Sms): 实现了短信发送的事件机制 2023-01-16 22:05:31 +08:00
李东云
b65818bfb6 docs(Sms): 补充所抛出异常的注释 2023-01-16 21:58:58 +08:00
李东云
1dbad8e5a6 feat(Listener): 添加了一个抽象监听器类,预先注入了一些属性 2023-01-16 21:56:28 +08:00
李东云
5a1a2a89bd perf(Sms): 修改抛出的异常类型,追加方法注释 2023-01-16 21:55:20 +08:00
李东云
8757908f3f feat(Email): 实现了邮件发送的事件机制 2023-01-16 21:23:44 +08:00
47 changed files with 12580 additions and 7439 deletions

44
.idea/HDK-Core.iml generated
View File

@@ -2,7 +2,6 @@
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="Singularity\HDK\Core\" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="Singularity\HDK\Test\Core\" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/recursion-context" />
@@ -13,7 +12,6 @@
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/code-unit" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/environment" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/exporter" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/resource-operations" />
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/promises" />
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/psr7" />
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/guzzle" />
@@ -64,9 +62,6 @@
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/http-message" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/exception-handler" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/macroable" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/resource" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/paginator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/engine" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/pool" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/event" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/validation" />
@@ -85,7 +80,6 @@
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/manifest" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/version" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-timer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/phpunit" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-text-template" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-code-coverage" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-invoker" />
@@ -135,14 +129,48 @@
<excludeFolder url="file://$MODULE_DIR$/vendor/nunomaduro/collision" />
<excludeFolder url="file://$MODULE_DIR$/vendor/pestphp/pest" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/stopwatch" />
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/test-time" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpstan/phpstan" />
<excludeFolder url="file://$MODULE_DIR$/vendor/pestphp/pest-plugin" />
<excludeFolder url="file://$MODULE_DIR$/vendor/friendsofphp/php-cs-fixer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/pest-plugin-test-time" />
<excludeFolder url="file://$MODULE_DIR$/vendor/filp/whoops" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/deprecations" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/phpunit" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/engine" />
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/pest-plugin-test-time" />
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/test-time" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/coordinator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/engine-contract" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/resource" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/paginator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/guzzle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-foundation" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/collection" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/db" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/pipeline" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/tappable" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/serializer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/code-parser" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/codec" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/conditionable" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/coroutine" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/serializer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/stringable" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/support" />
<excludeFolder url="file://$MODULE_DIR$/vendor/brianium/paratest" />
<excludeFolder url="file://$MODULE_DIR$/vendor/fidry/cpu-core-counter" />
<excludeFolder url="file://$MODULE_DIR$/vendor/friendsofhyperf/pest-plugin-hyperf" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hyperf/crontab" />
<excludeFolder url="file://$MODULE_DIR$/vendor/jean85/pretty-package-versions" />
<excludeFolder url="file://$MODULE_DIR$/vendor/nunomaduro/termwind" />
<excludeFolder url="file://$MODULE_DIR$/vendor/pestphp/pest-plugin-arch" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/reflection-common" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/reflection-docblock" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/type-resolver" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpstan/phpdoc-parser" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/clock" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php83" />
<excludeFolder url="file://$MODULE_DIR$/vendor/ta-tikoma/phpunit-architecture-test" />
<excludeFolder url="file://$MODULE_DIR$/vendor/webmozart/assert" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />

View File

@@ -1,8 +1,7 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PhpCSFixerValidationInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpDocSignatureInspection" enabled="true" level="INFORMATION" enabled_by_default="true" />
<inspection_tool class="PhpPropertyOnlyWrittenInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpStanGlobal" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
</profile>
</component>

249
.idea/php.xml generated
View File

@@ -20,147 +20,176 @@
</component>
<component name="PhpIncludePathManager">
<include_path>
<path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
<path value="$PROJECT_DIR$/vendor/sebastian/lines-of-code" />
<path value="$PROJECT_DIR$/vendor/sebastian/type" />
<path value="$PROJECT_DIR$/vendor/sebastian/version" />
<path value="$PROJECT_DIR$/vendor/sebastian/cli-parser" />
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit" />
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
<path value="$PROJECT_DIR$/vendor/sebastian/resource-operations" />
<path value="$PROJECT_DIR$/vendor/guzzlehttp/promises" />
<path value="$PROJECT_DIR$/vendor/guzzlehttp/psr7" />
<path value="$PROJECT_DIR$/vendor/guzzlehttp/guzzle" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/tea-xml" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/darabonba-openapi" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/openapi-util" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/tea" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/tea-utils" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/gateway-spi" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/endpoint-util" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/dysmsapi-20170525" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/credentials" />
<path value="$PROJECT_DIR$/vendor/justinrainbow/json-schema" />
<path value="$PROJECT_DIR$/vendor/graham-campbell/result-type" />
<path value="$PROJECT_DIR$/vendor/composer" />
<path value="$PROJECT_DIR$/vendor/fig/http-message-util" />
<path value="$PROJECT_DIR$/vendor/lmc/http-constants" />
<path value="$PROJECT_DIR$/vendor/psr/cache" />
<path value="$PROJECT_DIR$/vendor/psr/http-server-handler" />
<path value="$PROJECT_DIR$/vendor/psr/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/psr/http-server-middleware" />
<path value="$PROJECT_DIR$/vendor/psr/http-message" />
<path value="$PROJECT_DIR$/vendor/psr/container" />
<path value="$PROJECT_DIR$/vendor/psr/http-client" />
<path value="$PROJECT_DIR$/vendor/psr/log" />
<path value="$PROJECT_DIR$/vendor/psr/http-factory" />
<path value="$PROJECT_DIR$/vendor/seld/phar-utils" />
<path value="$PROJECT_DIR$/vendor/seld/jsonlint" />
<path value="$PROJECT_DIR$/vendor/seld/signal-handler" />
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
<path value="$PROJECT_DIR$/vendor/nikic/fast-route" />
<path value="$PROJECT_DIR$/vendor/react/promise" />
<path value="$PROJECT_DIR$/vendor/roave/dont" />
<path value="$PROJECT_DIR$/vendor/hyperf/database" />
<path value="$PROJECT_DIR$/vendor/hyperf/contract" />
<path value="$PROJECT_DIR$/vendor/hyperf/di" />
<path value="$PROJECT_DIR$/vendor/hyperf/context" />
<path value="$PROJECT_DIR$/vendor/hyperf/logger" />
<path value="$PROJECT_DIR$/vendor/hyperf/http-server" />
<path value="$PROJECT_DIR$/vendor/hyperf/translation" />
<path value="$PROJECT_DIR$/vendor/hyperf/framework" />
<path value="$PROJECT_DIR$/vendor/hyperf/config" />
<path value="$PROJECT_DIR$/vendor/hyperf/redis" />
<path value="$PROJECT_DIR$/vendor/hyperf/constants" />
<path value="$PROJECT_DIR$/vendor/hyperf/dispatcher" />
<path value="$PROJECT_DIR$/vendor/hyperf/server" />
<path value="$PROJECT_DIR$/vendor/hyperf/utils" />
<path value="$PROJECT_DIR$/vendor/hyperf/http-message" />
<path value="$PROJECT_DIR$/vendor/hyperf/exception-handler" />
<path value="$PROJECT_DIR$/vendor/hyperf/macroable" />
<path value="$PROJECT_DIR$/vendor/hyperf/resource" />
<path value="$PROJECT_DIR$/vendor/hyperf/paginator" />
<path value="$PROJECT_DIR$/vendor/hyperf/engine" />
<path value="$PROJECT_DIR$/vendor/hyperf/pool" />
<path value="$PROJECT_DIR$/vendor/hyperf/event" />
<path value="$PROJECT_DIR$/vendor/hyperf/validation" />
<path value="$PROJECT_DIR$/vendor/hyperf/session" />
<path value="$PROJECT_DIR$/vendor/nesbot/carbon" />
<path value="$PROJECT_DIR$/vendor/php-di/phpdoc-reader" />
<path value="$PROJECT_DIR$/vendor/teapot/status-code" />
<path value="$PROJECT_DIR$/vendor/vlucas/phpdotenv" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/credentials" />
<path value="$PROJECT_DIR$/vendor/adbario/php-dot-notation" />
<path value="$PROJECT_DIR$/vendor/egulias/email-validator" />
<path value="$PROJECT_DIR$/vendor/laminas/laminas-mime" />
<path value="$PROJECT_DIR$/vendor/friendsofphp/php-cs-fixer" />
<path value="$PROJECT_DIR$/vendor/swoole/ide-helper" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/endpoint-util" />
<path value="$PROJECT_DIR$/vendor/teapot/status-code" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/dysmsapi-20170525" />
<path value="$PROJECT_DIR$/vendor/laminas/laminas-stdlib" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/type-resolver" />
<path value="$PROJECT_DIR$/vendor/monolog/monolog" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-docblock" />
<path value="$PROJECT_DIR$/vendor/egulias/email-validator" />
<path value="$PROJECT_DIR$/vendor/justinrainbow/json-schema" />
<path value="$PROJECT_DIR$/vendor/laminas/laminas-mime" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-common" />
<path value="$PROJECT_DIR$/vendor/pestphp/pest-plugin" />
<path value="$PROJECT_DIR$/vendor/pestphp/pest" />
<path value="$PROJECT_DIR$/vendor/myclabs/php-enum" />
<path value="$PROJECT_DIR$/vendor/friendsofhyperf/pest-plugin-hyperf" />
<path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
<path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
<path value="$PROJECT_DIR$/vendor/graham-campbell/result-type" />
<path value="$PROJECT_DIR$/vendor/phar-io/version" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
<path value="$PROJECT_DIR$/vendor/phpstan/phpstan" />
<path value="$PROJECT_DIR$/vendor/pestphp/pest-plugin-arch" />
<path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-invoker" />
<path value="$PROJECT_DIR$/vendor/phpstan/phpdoc-parser" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php73" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php80" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-invoker" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-ctype" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php81" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php72" />
<path value="$PROJECT_DIR$/vendor/symfony/translation" />
<path value="$PROJECT_DIR$/vendor/symfony/serializer" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php80" />
<path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php72" />
<path value="$PROJECT_DIR$/vendor/symfony/translation" />
<path value="$PROJECT_DIR$/vendor/symfony/options-resolver" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
<path value="$PROJECT_DIR$/vendor/symfony/mailer" />
<path value="$PROJECT_DIR$/vendor/symfony/filesystem" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
<path value="$PROJECT_DIR$/vendor/symfony/finder" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php83" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/finder" />
<path value="$PROJECT_DIR$/vendor/symfony/mime" />
<path value="$PROJECT_DIR$/vendor/symfony/string" />
<path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/stopwatch" />
<path value="$PROJECT_DIR$/vendor/symfony/mime" />
<path value="$PROJECT_DIR$/vendor/symfony/process" />
<path value="$PROJECT_DIR$/vendor/symfony/console" />
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
<path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
<path value="$PROJECT_DIR$/vendor/brianium/paratest" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-grapheme" />
<path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
<path value="$PROJECT_DIR$/vendor/doctrine/lexer" />
<path value="$PROJECT_DIR$/vendor/doctrine/inflector" />
<path value="$PROJECT_DIR$/vendor/doctrine/annotations" />
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
<path value="$PROJECT_DIR$/vendor/ergebnis/http-method" />
<path value="$PROJECT_DIR$/vendor/firebase/php-jwt" />
<path value="$PROJECT_DIR$/vendor/jetbrains/phpstorm-attributes" />
<path value="$PROJECT_DIR$/vendor/lizhichao/one-sm" />
<path value="$PROJECT_DIR$/vendor/phpoption/phpoption" />
<path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" />
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
<path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
<path value="$PROJECT_DIR$/vendor/sebastian/complexity" />
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
<path value="$PROJECT_DIR$/vendor/swoole/ide-helper" />
<path value="$PROJECT_DIR$/vendor/pestphp/pest" />
<path value="$PROJECT_DIR$/vendor/pestphp/pest-plugin" />
<path value="$PROJECT_DIR$/vendor/composer" />
<path value="$PROJECT_DIR$/vendor/lmc/http-constants" />
<path value="$PROJECT_DIR$/vendor/psr/cache" />
<path value="$PROJECT_DIR$/vendor/fig/http-message-util" />
<path value="$PROJECT_DIR$/vendor/psr/http-server-middleware" />
<path value="$PROJECT_DIR$/vendor/psr/http-message" />
<path value="$PROJECT_DIR$/vendor/psr/http-server-handler" />
<path value="$PROJECT_DIR$/vendor/psr/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/psr/log" />
<path value="$PROJECT_DIR$/vendor/psr/clock" />
<path value="$PROJECT_DIR$/vendor/psr/container" />
<path value="$PROJECT_DIR$/vendor/psr/http-client" />
<path value="$PROJECT_DIR$/vendor/seld/phar-utils" />
<path value="$PROJECT_DIR$/vendor/seld/jsonlint" />
<path value="$PROJECT_DIR$/vendor/psr/http-factory" />
<path value="$PROJECT_DIR$/vendor/filp/whoops" />
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
<path value="$PROJECT_DIR$/vendor/nikic/fast-route" />
<path value="$PROJECT_DIR$/vendor/seld/signal-handler" />
<path value="$PROJECT_DIR$/vendor/fidry/cpu-core-counter" />
<path value="$PROJECT_DIR$/vendor/hyperf/database" />
<path value="$PROJECT_DIR$/vendor/hyperf/pipeline" />
<path value="$PROJECT_DIR$/vendor/react/promise" />
<path value="$PROJECT_DIR$/vendor/roave/dont" />
<path value="$PROJECT_DIR$/vendor/hyperf/coordinator" />
<path value="$PROJECT_DIR$/vendor/doctrine/inflector" />
<path value="$PROJECT_DIR$/vendor/hyperf/serializer" />
<path value="$PROJECT_DIR$/vendor/doctrine/annotations" />
<path value="$PROJECT_DIR$/vendor/hyperf/contract" />
<path value="$PROJECT_DIR$/vendor/hyperf/collection" />
<path value="$PROJECT_DIR$/vendor/doctrine/lexer" />
<path value="$PROJECT_DIR$/vendor/hyperf/logger" />
<path value="$PROJECT_DIR$/vendor/ergebnis/http-method" />
<path value="$PROJECT_DIR$/vendor/hyperf/tappable" />
<path value="$PROJECT_DIR$/vendor/firebase/php-jwt" />
<path value="$PROJECT_DIR$/vendor/hyperf/di" />
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
<path value="$PROJECT_DIR$/vendor/hyperf/context" />
<path value="$PROJECT_DIR$/vendor/doctrine/deprecations" />
<path value="$PROJECT_DIR$/vendor/hyperf/translation" />
<path value="$PROJECT_DIR$/vendor/phpoption/phpoption" />
<path value="$PROJECT_DIR$/vendor/hyperf/framework" />
<path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" />
<path value="$PROJECT_DIR$/vendor/hyperf/http-server" />
<path value="$PROJECT_DIR$/vendor/jetbrains/phpstorm-attributes" />
<path value="$PROJECT_DIR$/vendor/hyperf/coroutine" />
<path value="$PROJECT_DIR$/vendor/lizhichao/one-sm" />
<path value="$PROJECT_DIR$/vendor/hyperf/constants" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
<path value="$PROJECT_DIR$/vendor/hyperf/codec" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
<path value="$PROJECT_DIR$/vendor/hyperf/config" />
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
<path value="$PROJECT_DIR$/vendor/hyperf/redis" />
<path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
<path value="$PROJECT_DIR$/vendor/hyperf/server" />
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
<path value="$PROJECT_DIR$/vendor/hyperf/utils" />
<path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
<path value="$PROJECT_DIR$/vendor/hyperf/crontab" />
<path value="$PROJECT_DIR$/vendor/sebastian/complexity" />
<path value="$PROJECT_DIR$/vendor/hyperf/dispatcher" />
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
<path value="$PROJECT_DIR$/vendor/hyperf/code-parser" />
<path value="$PROJECT_DIR$/vendor/sebastian/version" />
<path value="$PROJECT_DIR$/vendor/hyperf/conditionable" />
<path value="$PROJECT_DIR$/vendor/sebastian/cli-parser" />
<path value="$PROJECT_DIR$/vendor/hyperf/http-message" />
<path value="$PROJECT_DIR$/vendor/sebastian/lines-of-code" />
<path value="$PROJECT_DIR$/vendor/hyperf/exception-handler" />
<path value="$PROJECT_DIR$/vendor/sebastian/type" />
<path value="$PROJECT_DIR$/vendor/hyperf/macroable" />
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
<path value="$PROJECT_DIR$/vendor/hyperf/db" />
<path value="$PROJECT_DIR$/vendor/ta-tikoma/phpunit-architecture-test" />
<path value="$PROJECT_DIR$/vendor/hyperf/engine-contract" />
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit" />
<path value="$PROJECT_DIR$/vendor/hyperf/support" />
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
<path value="$PROJECT_DIR$/vendor/hyperf/engine" />
<path value="$PROJECT_DIR$/vendor/guzzlehttp/psr7" />
<path value="$PROJECT_DIR$/vendor/hyperf/stringable" />
<path value="$PROJECT_DIR$/vendor/guzzlehttp/guzzle" />
<path value="$PROJECT_DIR$/vendor/hyperf/resource" />
<path value="$PROJECT_DIR$/vendor/webmozart/assert" />
<path value="$PROJECT_DIR$/vendor/hyperf/paginator" />
<path value="$PROJECT_DIR$/vendor/guzzlehttp/promises" />
<path value="$PROJECT_DIR$/vendor/hyperf/validation" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/tea-xml" />
<path value="$PROJECT_DIR$/vendor/hyperf/guzzle" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/darabonba-openapi" />
<path value="$PROJECT_DIR$/vendor/hyperf/pool" />
<path value="$PROJECT_DIR$/vendor/nunomaduro/termwind" />
<path value="$PROJECT_DIR$/vendor/hyperf/event" />
<path value="$PROJECT_DIR$/vendor/nunomaduro/collision" />
<path value="$PROJECT_DIR$/vendor/nesbot/carbon" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/tea-utils" />
<path value="$PROJECT_DIR$/vendor/php-di/phpdoc-reader" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/gateway-spi" />
<path value="$PROJECT_DIR$/vendor/hyperf/session" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/openapi-util" />
<path value="$PROJECT_DIR$/vendor/jean85/pretty-package-versions" />
<path value="$PROJECT_DIR$/vendor/alibabacloud/tea" />
<path value="$PROJECT_DIR$/vendor/spatie/test-time" />
<path value="$PROJECT_DIR$/vendor/spatie/pest-plugin-test-time" />
<path value="$PROJECT_DIR$/vendor/friendsofphp/php-cs-fixer" />
<path value="$PROJECT_DIR$/vendor/symfony/options-resolver" />
<path value="$PROJECT_DIR$/vendor/symfony/stopwatch" />
<path value="$PROJECT_DIR$/vendor/phpstan/phpstan" />
<path value="$PROJECT_DIR$/vendor/doctrine/deprecations" />
<path value="$PROJECT_DIR$/vendor/hyperf/coordinator" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.0" />
<component name="PhpProjectSharedConfiguration" php_language_level="8.1" />
<component name="PhpStan">
<PhpStan_settings>
<PhpStanConfiguration tool_path="$PROJECT_DIR$/vendor/bin/phpstan" />

View File

@@ -1,4 +1,224 @@
# 版本更新日志
## [1.0.0-alpha.2](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v1.0.0-alpha.1...v1.0.0-alpha.2) (2023-07-21)
### 🐛 Bug Fixes | Bug 修复
* **controller:** 修复方法访问级别不足以继承的问题 ([b30c844](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/b30c84488b7f85447bd802df77c9decbf315ed85))
## [1.0.0-alpha.1](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v1.0.0-alpha.0...v1.0.0-alpha.1) (2023-07-21)
### 📦‍ Build System | 打包构建
* **composer:** 更新依赖 ([a8ec7d8](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/a8ec7d82556c2fb8fbe1e356eb6d1936401c810a))
* **release:** 增加 alpha 标识,准备正式版 ([f1948ab](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/f1948ab0fe4594140eede8e52f113963d98a8338))
## [1.0.0-alpha.0](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.23...v1.0.0-alpha.0) (2023-07-21)
### ✏️ Documentation | 文档
* **utils:** 移除了导致编辑器出错的注解 ([7ccf36b](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/7ccf36b398f86a31c7d8dde6ff24f0d9828cfb80))
### ✨ Features | 新功能
* **controller:** 增加了一个 Rest 风格的 trait ([68844a6](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/68844a6132059da89f69a34ba59229c40e5bcace))
* **trait:** 增加了分页响应的统一处理方法 ([fd788a7](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/fd788a7eb804b7fe085346d817123c04c8bd0d01))
### [0.2.23](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.22...v0.2.23) (2023-07-07)
### 🐛 Bug Fixes | Bug 修复
* **i18n:** 修复获取偏好语言失败的问题 ([722d124](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/722d124e1ed87c493dfb8841212b408717444d98))
### [0.2.22](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.21...v0.2.22) (2023-07-06)
### 🐛 Bug Fixes | Bug 修复
* **service:** 修复 http 请求类中无效的 query ([a6ec695](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/a6ec6951a9a68a4c5144aee97638486826d6af84))
### [0.2.21](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.20...v0.2.21) (2023-07-05)
### ⚡ Performance Improvements | 性能优化
* 适配已弃用的命名空间 ([8616c5f](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/8616c5f61cc8e69c9d61f42f5dc5d18e7c79fd7b))
### 🚀 Chore | 构建/工程依赖/工具
* **deprecated:** 声明弃用了 SessionMiddleware ([2b0374b](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/2b0374bcc83a5534358a7fce34b723e3bd38dceb))
### [0.2.20](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.19...v0.2.20) (2023-06-19)
### ✨ Features | 新功能
* **handler:** 增加了 restful 的支持 ([8974ee5](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/8974ee595b3411bac086c3046eb24ba44087ecc7))
### [0.2.19](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.18...v0.2.19) (2023-06-02)
### 📦‍ Build System | 打包构建
* **composer:** 更新依赖 ([648fe6c](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/648fe6c8f32e2511f0c1a79dbafff8e889c1da7b))
### [0.2.18](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.17...v0.2.18) (2023-06-02)
### 🐛 Bug Fixes | Bug 修复
* 修复 http 请求失效的问题 ([43ebd05](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/43ebd0546abb25446e83522fd0c069dd0e6880c7))
### 📦‍ Build System | 打包构建
* 更新被弃用的写法 ([c748cbd](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/c748cbd3e322b5a926996fc2ee958b2e2a911d7c))
### [0.2.17](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.16...v0.2.17) (2023-05-06)
### 📦‍ Build System | 打包构建
* **composer:** 更新依赖 ([d22bd3e](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/d22bd3ee587f7799b33a28015c148e50afe79107))
### ✨ Features | 新功能
* **xml:** 实现了解析xml的方法 ([be818b7](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/be818b708011bb05a65752380248c8307938d110))
### [0.2.16](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.15...v0.2.16) (2023-04-25)
### 🐛 Bug Fixes | Bug 修复
* **extend:** 修复未传入 extends 不存在缺省值的问题 ([77f3141](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/77f3141c56a09905e0c357c1b183c1c8831c9acd))
### ✨ Features | 新功能
* **handler:** 补全了各种错误的状态码 ([0247dd4](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/0247dd415c2a62c21b5a6fbb15ab1e6ce3d1a316))
### [0.2.15](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.14...v0.2.15) (2023-04-13)
### 🐛 Bug Fixes | Bug 修复
* **coreMiddleware:** 修复restful 无法分页的问题 ([a6b71db](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/a6b71dbb037624ac69eddc1e5b1d671ab45b06ae))
### ✨ Features | 新功能
* 默认绑定 CoreMiddleware 的映射关系 ([5e5792b](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/5e5792b28ca13cc8833280ba3d26ec588c445350))
### [0.2.14](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.13...v0.2.14) (2023-04-12)
### ✨ Features | 新功能
* **handler:** 补充 restful 响应的状态码 ([e69c149](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/e69c1494c3ec0a8d26341f1891d7d067511e8baf))
### [0.2.13](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.12...v0.2.13) (2023-04-11)
### ✨ Features | 新功能
* **xml:** 增加了 xml 生成的方法及测试用例 ([90a521f](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/90a521f90acee7fd6efe6f0a554e749c16fadc1c))
### [0.2.12](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.11...v0.2.12) (2023-04-10)
### 📦‍ Build System | 打包构建
* **composer:** 更新依赖以兼容 nano ([7e5cb89](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/7e5cb89dfe1c09390e78cdd527c60151f2cd0418))
* **phpstan:** fix ([c25e6ee](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/c25e6eed52e83d2ca62fc3d0cf83f508a1045c5a))
* **scripts:** 更新脚本 ([4ba0cb8](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/4ba0cb83f5dc88817260cb2b2dfde491c6b5ba75))
### [0.2.11](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.10...v0.2.11) (2023-04-03)
### 📦‍ Build System | 打包构建
* **composer:** 更新依赖 ([78b56a6](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/78b56a6aa9038743be7df9a17787b94771e226c3))
* **composer:** 更新依赖 ([c991c31](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/c991c312609e7501c7adad28ec8229efad717db0))
### ✨ Features | 新功能
* **i18n:** 引入了 symfony 的 Accept-Language 机制 ([859a1a1](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/859a1a1f2aa683f9f026652952d1a03ba5d7be02))
### [0.2.10](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.9...v0.2.10) (2023-03-21)
### 📦‍ Build System | 打包构建
* **composer:** 只留下了腾讯源,更新依赖 ([afec642](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/afec6424545daa3b3f2a4b91e97e359b4a840a19))
* **composer:** 只留下了腾讯源,更新依赖 ([b2debf9](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/b2debf9c135554a15639c299f183c43f3682545b))
* **composer:** 更新依赖 ([70ad307](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/70ad3078b1ddeeeb0179dd44770e959ecf072fed))
### [0.2.9](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.8...v0.2.9) (2023-03-15)
### 🐛 Bug Fixes | Bug 修复
* 修复了一处大小写错误 ([2d2a535](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/2d2a535fd2c1ae13195f13498864540b503edd1e))
### ✨ Features | 新功能
* 增加了inArray、hasExtends方法 ([de96e28](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/de96e288c3429c58deed15ea667a5e15a34fb81f))
* 增加了对 session 中间件配置 cookie 方式的补充 ([a618af5](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/a618af5ab353f478dd4bcce18a7b84f611fd0c7a))
* 增加默认api风格参数 ([e33c115](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/e33c1159388efa3590e81f484c01a66d21f8b574))
* 实现了通过中间件设置是否 restful 的逻辑 ([2d2148f](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/2d2148f3ecabef09801a225632430bf103dbf218))
* 添加了 http 请求服务 ([7c1efe1](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/7c1efe1a1f18f082ed7b7b6383112034982e2893))
* **api:** 增加了可以使用中间件定制是否 restful 的逻辑 ([b8c3d6d](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/b8c3d6d06810fb920df200a4d75746b49e2fbd07))
### [0.2.8](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.7...v0.2.8) (2023-02-03)
### 🐛 Bug Fixes | Bug 修复
* **commonHandler:** 修复了一处兼容问题 ([c8f9b79](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/c8f9b793ee7c2ba4d77a2779b6825211dcf52636))
### [0.2.7](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.6...v0.2.7) (2023-02-02)
### ⚡ Performance Improvements | 性能优化
* **Sms:** 修改抛出的异常类型,追加方法注释 ([5a1a2a8](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/5a1a2a89bd7d706a6e8d1ef567c59969d8d63554))
### ✨ Features | 新功能
* **Email:** 实现了邮件发送的事件机制 ([8757908](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/8757908f3f8a6dff5516bd6e449c8dd3952ec2cd))
* **Listener:** 添加了一个抽象监听器类,预先注入了一些属性 ([1dbad8e](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/1dbad8e5a65d299b9a56b6a5c4759be5c3736707))
* **Sms:** 实现了短信发送的事件机制 ([5151787](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/51517879820de832395efc40bb308a736f33f131))
### ✏️ Documentation | 文档
* **README:** 修复一直报错的文件名 ([135db1b](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/135db1bf6aeeedbb0d59405567bb4837f3221e49))
* **Sms:** 补充所抛出异常的注释 ([b65818b](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/b65818bfb6d8368514d517c31dd6b6696b2d08be))
### ✅ Tests | 测试
* **extend:** 补充测试用例 ([e41847a](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/e41847a2340916de24726f8266dca8b514b4edd3))
### 🐛 Bug Fixes | Bug 修复
* **extend:** 修复了解析不到为空不为数组的问题 ([099ab60](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/099ab601030caef52806f5b9ec4d62fb27b08e72))
### 💄 Styles | 风格
* **cs-fixer:** prettier ([a729270](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/commit/a729270fac57cd617e8f166bb59f9ccffe33358b))
### [0.2.6](http://124.126.16.154:8888/singularity/HyperfDevelopmentKitCore/compare/v0.2.5...v0.2.6) (2023-01-16)

View File

@@ -22,7 +22,7 @@ After cloning this repository, change into the newly created directory and run
composer config secure-http false \
&& composer config repo.lux-map composer https://satis.luxcreo.cn/ \
&& composer require singularity/hdk-core \
&& php bin/hyperf vendor:publish singularity/hdk-core
&& php bin/hyperf.php vendor:publish singularity/hdk-core
```
This will install all dependencies needed for the project.

View File

@@ -1 +1 @@
0.2.6
1.0.0-alpha.2

View File

@@ -15,55 +15,66 @@
}
],
"require": {
"php": "~8.0",
"php": "^8.1",
"ext-redis": "^5.3",
"ext-swoole": "*",
"composer/composer": ">=2.0",
"ergebnis/http-method": "^2.2",
"hyperf/config": "3.0.*",
"hyperf/constants": "3.0.*",
"hyperf/context": "3.0.*",
"hyperf/database": "3.0.*",
"hyperf/di": "3.0.*",
"hyperf/framework": "3.0.*",
"hyperf/http-server": "3.0.*",
"hyperf/logger": "3.0.*",
"hyperf/redis": "3.0.*",
"hyperf/resource": "3.0.*",
"hyperf/translation": "3.0.*",
"hyperf/config": "^3.0.18",
"hyperf/constants": "^3.0.18",
"hyperf/context": "^3.0.18",
"hyperf/di": "^3.0.18",
"hyperf/framework": "^3.0.18",
"hyperf/logger": "^3.0.18",
"hyperf/redis": "^3.0.18",
"hyperf/resource": "^3.0.18",
"hyperf/translation": "^3.0.18",
"jetbrains/phpstorm-attributes": "^1.0",
"lmc/http-constants": "^1.2",
"myclabs/php-enum": "^1.8",
"roave/dont": "^1.5",
"symfony/http-foundation": "^6.0",
"symfony/polyfill-php81": "^1.26",
"teapot/status-code": "^1.1"
"teapot/status-code": "^1.1",
"ext-libxml": "*",
"ext-dom": "*"
},
"require-dev": {
"alibabacloud/dysmsapi-20170525": "^2.0",
"firebase/php-jwt": "^6.1",
"friendsofhyperf/pest-plugin-hyperf": "^3.0.0",
"friendsofphp/php-cs-fixer": "^3.13",
"guzzlehttp/guzzle": "^7.5",
"hyperf/session": "3.0.*",
"hyperf/validation": "3.0.*",
"pestphp/pest": "^1.22",
"hyperf/crontab": "^3.0.18",
"hyperf/database": "^3.0.18",
"hyperf/db": "^3.0.18",
"hyperf/guzzle": "^3.0.18",
"hyperf/session": "^3.0.18",
"hyperf/validation": "^3.0.18",
"phpstan/phpstan": "^1.9",
"phpunit/phpunit": "^9.5",
"roave/security-advisories": "dev-latest",
"spatie/pest-plugin-test-time": "^1.1",
"spatie/pest-plugin-test-time": "^2.0",
"swoole/ide-helper": "*",
"symfony/mailer": "^6.0"
"symfony/mailer": "^6.0",
"symfony/serializer": "^6.0"
},
"suggest": {
"firebase/php-jwt": "JWT 鉴权必需",
"hyperf/session": "Session 鉴权必需",
"hyperf/session": "^3.0.18",
"symfony/mailer": "用于发送电子邮件",
"guzzlehttp/guzzle": "需要发起 http 请求时必需",
"symfony/serializer": "处理 XML 必需",
"ext-dom": "处理 XML 必需",
"ext-libxml": "处理 XML 必需",
"hyperf/guzzle": "^3.0.18",
"alibabacloud/dysmsapi-20170525": "阿里云短信服务必需"
},
"config": {
"optimize-autoloader": true,
"sort-packages": true,
"secure-http": false
"secure-http": false,
"allow-plugins": {
"pestphp/pest-plugin": true
}
},
"autoload": {
"psr-4": {
@@ -79,7 +90,7 @@
"prefer-stable": true,
"scripts": {
"post-root-package-install": [],
"test": "vendor/bin/pest $1",
"test": "vendor/bin/pest --prepend tests/prepend.php --coroutine $1",
"cs-fix": "vendor/bin/php-cs-fixer fix $1 --rules=@PSR12 --allow-risky=yes",
"analyse": "vendor/bin/phpstan analyse $1",
"ci": [
@@ -95,17 +106,9 @@
"url": "https://satis.luxcreo.cn/"
},
"packagist": {
"type": "composer",
"url": "https://mirrors.aliyun.com/composer/"
},
"packagist-tx": {
"type": "composer",
"url": "https://mirrors.cloud.tencent.com/composer/"
},
"packagist-hw": {
"type": "composer",
"url": "https://repo.huaweicloud.com/repository/php/"
}
},
"version": "0.2.6"
"version": "1.0.0-alpha.2"
}

17787
composer.lock generated Executable file → Normal file

File diff suppressed because it is too large Load Diff

76
docs/Email.md Normal file
View File

@@ -0,0 +1,76 @@
# Email | 邮件
提供一套通用 Service 用于定制需求,和一套现成的事件/监听器用于异步发送。
## 服务类
[\Singularity\HDK\Core\Service\EmailService](../src/Service/EmailService.php)
* 发送纯文本邮件的 `\Singularity\HDK\Core\Service\EmailService::sendText()`
* 发送 Html 富文本邮件的 `\Singularity\HDK\Core\Service\EmailService::sendHtml()`
## 事件机制
> 这种方式无法监听邮件发送的结果!
>
> 如果你需要根据邮件发送的结果进行处理,
> 请使用服务类进行自定义
更好的方法可能是在事件发生后触发异步队列,
但如果将异步队列封装在本包中,
相当于强制引用本库的项目使用异步队列机制,
这是我们不愿意看到的。
所以这里的监听器只是集成了同步发送的操作。
如果你想要定义更好的设计,
你可以直接使用提供的 Service 类进行定制。
> 或许这里还有优化空间😄
### 事件
[\Singularity\HDK\Core\Events\EmailWillSent](../src/Events/EmailWillSent.php)
### 监听器
[\Singularity\HDK\Core\Listener\EmailWillSentListener](../src/Listener/EmailWillSentListener.php)
### 使用方法
监听器已经通过 [ConfigProvider](../src/ConfigProvider.php) 机制注册,
所以你只需要在要发送邮件的地方调度这个事件即可。
> 这也就意味着,你无法调用这个事件,但不触发这个监听器。
> 如果你有这样做的必要,请创建一个自己的事件。
> 这也是为了保证功能的完整性和原子性。
具体使用方法,如下代码所示:
```php
<?php
namespace App\Service;
use Hyperf\Di\Annotation\Inject;
use Psr\EventDispatcher\EventDispatcherInterface;
use App\Event\UserRegistered;use Singularity\HDK\Core\Events\EmailWillSent;
class UserService
{
/**
* @var EventDispatcherInterface
*/
#[Inject]
private $eventDispatcher;
public function register()
{
// 我们假设存在 User 这个实体
$user = new User();
$result = $user->save();
// ↓
// 这里 dispatch(object $event) 会逐个运行监听该事件的监听器
$this->eventDispatcher->dispatch(new EmailWillSent(
target: $user->mobile,
subject: '注册成功通知',
type: 'html', // 默认 text 可以不传
content: <<<HTML
<h1>恭喜你,注册成功!</h1>
HTML,
));
// ↑
return $result;
}
}
```

12
docs/REST 控制器.md Normal file
View File

@@ -0,0 +1,12 @@
# REST 资源控制器支持
## 列表的筛选、排序
* [**RestfulList**](../src/Traits/RestfulList.php)
### RestfulList
在 AbstractController 中已经默认进行了集成
- parseParameters 用来解析请求
- responseFormatter 用来将 builder 转化成响应
- restSelect 额外的语法糖,调用了上面的两个方法

75
docs/Sms.md Normal file
View File

@@ -0,0 +1,75 @@
# SMS | 短信
提供一套通用 Service 用于定制需求,和一套现成的事件/监听器用于异步发送。
## 服务类
[\Singularity\HDK\Core\Service\SmsService](../src/Service/SmsService.php)
* 发送国内短信的 `\Singularity\HDK\Core\Service\SmsService::sendSmsCountryside()`
## 事件机制
> 这种方式无法监听短信发送的结果!
>
> 如果你需要根据短信发送的结果进行处理,
> 请使用服务类进行自定义
更好的方法可能是在事件发生后触发异步队列,
但如果将异步队列封装在本包中,
相当于强制引用本库的项目使用异步队列机制,
这是我们不愿意看到的。
所以这里的监听器只是集成了同步发送的操作。
如果你想要定义更好的设计,
你可以直接使用提供的 Service 类进行定制。
> 或许这里还有优化空间😄
### 事件
[\Singularity\HDK\Core\Events\SmsWillSent](../src/Events/SmsWillSent.php)
### 监听器
[\Singularity\HDK\Core\Listener\SmsWillSentListener](../src/Listener/SmsWillSentListener.php)
### 使用方法
监听器已经通过 [ConfigProvider](../src/ConfigProvider.php) 机制注册,
所以你只需要在要发送短信的地方调度这个事件即可。
> 这也就意味着,你无法调用这个事件,但不触发这个监听器。
> 如果你有这样做的必要,请创建一个自己的事件。
> 这也是为了保证功能的完整性和原子性。
具体使用方法,如下代码所示:
```php
<?php
namespace App\Service;
use Hyperf\Di\Annotation\Inject;
use Psr\EventDispatcher\EventDispatcherInterface;
use App\Event\UserRegistered;use Singularity\HDK\Core\Events\EmailWillSent;
class UserService
{
/**
* @var EventDispatcherInterface
*/
#[Inject]
private $eventDispatcher;
public function register()
{
// 我们假设存在 User 这个实体
$user = new User();
$result = $user->save();
// ↓
// 这里 dispatch(object $event) 会逐个运行监听该事件的监听器
$this->eventDispatcher->dispatch(new EmailWillSent(
target: $user->mobile,
subject: '注册成功通知',
type: 'html', // 默认 text 可以不传
content: <<<HTML
<h1>恭喜你,注册成功!</h1>
HTML,
));
// ↑
return $result;
}
}
```

View File

@@ -1,9 +1,13 @@
parameters:
level: 6
reportUnmatchedIgnoredErrors: false
checkGenericClassInNonGenericObjectType: false
paths:
- publish
- src
- tests
ignoreErrors:
- '#Constant BASE_PATH not found#'
- '#Property [a-zA-Z0-9\\_]+::\$[a-zA-Z0-9]+ is never written, only read.#'
- '#Property [a-zA-Z0-9\\_]+::\$[a-zA-Z0-9]+ is never written, only read\.#'
- '#Method [a-zA-Z0-9\\_]+::[a-zA-Z0-9]+\(\) is unused\.#'
- '#Method [a-zA-Z0-9\\_]+::[a-zA-Z0-9]+\(\) has parameter \$response with no value type specified in iterable type array\.#'

View File

@@ -9,6 +9,8 @@
declare(strict_types=1);
use function Hyperf\Support\env;
return [
// 响应
'response' => [

View File

@@ -1,8 +0,0 @@
#!/usr/bin/env sh
docker login harbor.luxcreo.cn -u php -p fTr6oVvqqdzVlYgnZhRPPAP54u7SmqGA
image_name=harbor.luxcreo.cn/php/composer-template
docker build --tag $image_name .
#docker push $image_name
#docker push ${image_name}-dev

View File

@@ -6,4 +6,5 @@ docker run \
-w "/srv/www" \
-v "$(pwd)":/srv/www \
-v ~/.ssh:/root/.ssh \
harbor.luxcreo.cn/library/hyperf:8.0-swoole /bin/ash
-v ~/.gitconfig:/root/.gitconfig \
harbor.luxcreo.cn/library/hyperf:8.1-swoole /bin/ash

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env sh
docker run --rm -it \
-v $(pwd):/app -e "GIT_AUTHOR_NAME=ch4o5" -e "EMAIL=dongyun.li@luxcreo.ai" \
detouched/standard-version:latest $1
-v $(pwd):/app -e "GIT_AUTHOR_NAME=$(git config user.name)" -e "EMAIL=$(git config user.email)" \
detouched/standard-version:latest -p=alpha $1

View File

@@ -14,6 +14,10 @@ namespace Singularity\HDK\Core;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Framework\Logger\StdoutLogger;
use Hyperf\HttpServer\Contract\CoreMiddlewareInterface;
use Singularity\HDK\Core\Listener\EmailWillSentListener;
use Singularity\HDK\Core\Listener\SmsWillSentListener;
use Singularity\HDK\Core\Middleware\CommonCoreMiddleware;
class ConfigProvider
{
@@ -25,6 +29,7 @@ class ConfigProvider
// 合并到 config/autoload/dependencies.php 文件
'dependencies' => [
StdoutLoggerInterface::class => StdoutLogger::class,
CoreMiddlewareInterface::class => CommonCoreMiddleware::class
],
// 合并到 config/autoload/annotations.php 文件
'annotations' => [
@@ -38,7 +43,10 @@ class ConfigProvider
'commands' => [
],
// 与 commands 类似
'listeners' => [],
'listeners' => [
EmailWillSentListener::class,
SmsWillSentListener::class
],
// 组件默认配置文件,即执行命令后会把 source 的对应的文件复制为 destination 对应的的文件
'publish' => [
[

View File

@@ -21,8 +21,8 @@ use Dont\DontToString;
use Hyperf\Contract\ContainerInterface;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Singularity\HDK\Core\Traits\RestfulList;
/**
* 抽象控制器基类
@@ -42,13 +42,11 @@ abstract class AbstractController
use DontSerialise;
use DontDeserialise;
use DontToString;
use RestfulList;
#[Inject]
protected ContainerInterface $container;
#[Inject]
protected RequestInterface $request;
#[Inject]
protected ResponseInterface $response;

View File

@@ -0,0 +1,50 @@
<?php
/**
* EmailWillSent.php@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/1/16
*/
namespace Singularity\HDK\Core\Events;
/**
* Singularity\HDK\Core\Events\EmailWillSent@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/1/16
*
* @link ../../docs/Email.md
*/
class EmailWillSent
{
public function __construct(
/**
* @var string|string[] $target
*/
public string|array $target,
/**
* @var non-empty-string $subject
*/
public string $subject,
/**
* @var non-empty-string $content
*/
public string $content,
/**
* @var string[] $cc
*/
public array $cc = [],
/**
* @var 'text'|'html' $type
*/
public string $type = 'text'
) {
}
}

View File

@@ -0,0 +1,48 @@
<?php
/**
* SmsWillSent.php@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/1/16
*/
namespace Singularity\HDK\Core\Events;
/**
* Singularity\HDK\Core\Events\SmsWillSent@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/1/16
*
* @link ../../docs/SMS.md
*/
class SmsWillSent
{
public function __construct(
/**
* @var non-empty-string $phone 目标手机号
* @example +8613700000001
* @example 8613700000001
* @example 13700000001
*/
public string $phone,
/**
* @var array<literal-string, literal-string|int>|null $templateParam 模板变量
*/
public ?array $templateParam = null,
/**
* @var literal-string|null $templateCode 模板代码
*/
public ?string $templateCode = null,
/**
* @var literal-string|null $signName 模板签名
*/
public ?string $signName = null,
) {
}
}

View File

@@ -7,6 +7,8 @@ use Singularity\HDK\Core\Constants\CommonErrorCode;
use Teapot\StatusCode\RFC\RFC7231;
use Throwable;
use function Hyperf\Config\config;
/**
* 用户无权访问
*/

View File

@@ -12,6 +12,8 @@ declare(strict_types=1);
namespace Singularity\HDK\Core\Exceptions\Handler;
use Carbon\Carbon;
use Hyperf\Codec\Json;
use Hyperf\Database\Exception\QueryException;
use Hyperf\Database\Model\ModelNotFoundException;
use Hyperf\Di\Annotation\Inject;
@@ -23,17 +25,21 @@ use Hyperf\HttpMessage\Exception\MethodNotAllowedHttpException;
use Hyperf\HttpMessage\Exception\NotFoundHttpException;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Utils\Codec\Json;
use Hyperf\Validation\ValidationException;
use Lmc\HttpConstants\Header;
use Psr\Http\Message\ResponseInterface;
use RedisException;
use Singularity\HDK\Core\Constants\CommonErrorCode;
use Singularity\HDK\Core\Exceptions\ValidateException;
use Singularity\HDK\Core\Service\ApiStyleService;
use Symfony\Component\Mailer\Exception\TransportException;
use Teapot\StatusCode\RFC\RFC4918;
use Teapot\StatusCode\RFC\RFC7231;
use Throwable;
use function Hyperf\Config\config;
use function Hyperf\Translation\__;
/**
* 通用异常处理
* Singularity\HDK\Utils\Exceptions\Handler\CommonHandler@hyperf-development-kit
@@ -44,17 +50,15 @@ use Throwable;
*/
class CommonHandler extends ExceptionHandler
{
/**
*
* @var RequestInterface|null
*/
#[Inject(required: false)]
private ?RequestInterface $request;
/**
* @var StdoutLogger
*/
#[Inject]
private StdoutLogger $logger;
#[Inject]
private ApiStyleService $apiStyleService;
/**
* {@inheritDoc}
*/
@@ -62,14 +66,18 @@ class CommonHandler extends ExceptionHandler
{
// 阻止异常冒泡
$this->stopPropagation();
$restful = config('common.response.restful');
$restful = $this->apiStyleService->get();
// $restful = config('common.response.restful');
$code_name = config('common.response.code_name');
$message_name = config('common.response.message_name');
$is_testing = config('app_status') === true;
$this->request?->url();
$is_debug = $this->request?->hasHeader('Postman-Token') || str_starts_with($this->request?->header('User-Agent'), 'apifox');
$is_debug = $this->request?->hasHeader('Postman-Token') || str_starts_with(
$this->request?->header('User-Agent', ''),
'apifox'
);
$error_type = $throwable::class;
$request_time = date('Y-m-d H:i:s');
$request_time = Carbon::now()->toDateTimeString();
$request_data = Json::encode($this->request?->getParsedBody());
$request_headers = Json::encode($this->request?->getHeaders());
// 901 程序语法错误
@@ -79,7 +87,10 @@ class CommonHandler extends ExceptionHandler
'42S22' => CommonErrorCode::PROGRAM_SQL_COLUMN_NOT_FOUND,
default => CommonErrorCode::PROGRAM_SQL_ERROR,
};
$data = [$code_name => $code, $message_name => CommonErrorCode::getMessage($is_testing ? $code : CommonErrorCode::PROGRAM_SQL_ERROR)];
$data = [
$code_name => $code,
$message_name => CommonErrorCode::getMessage($is_testing ? $code : CommonErrorCode::PROGRAM_SQL_ERROR),
];
if ($is_testing) {
$data['details'] = ['sql' => $throwable->getSql(), 'error' => $throwable->getMessage()];
}
@@ -89,24 +100,48 @@ class CommonHandler extends ExceptionHandler
$message = explode(': ', $throwable->getMessage());
$allow_method = explode(', ', $message[1]);
$code = CommonErrorCode::REQUEST_METHOD_ERROR;
$data = [$code_name => $code, $message_name => CommonErrorCode::getMessage($code, ['methods' => join(', ', $allow_method)]), 'currentMethod' => $this->request?->getMethod(), 'allowedMethod' => $allow_method];
$data = [
$code_name => $code,
$message_name => CommonErrorCode::getMessage($code, ['methods' => join(', ', $allow_method)]),
'currentMethod' => $this->request?->getMethod(),
'allowedMethod' => $allow_method,
];
$status_code = RFC7231::METHOD_NOT_ALLOWED;
}
// 验证失败
if ($throwable instanceof BadRequestHttpException) {
$data = [$code_name => CommonErrorCode::REQUEST_PARAMS_ERROR, $message_name => $is_testing ? $throwable->getMessage() : CommonErrorCode::getMessage(CommonErrorCode::SERVER_ERROR)];
$data = [
$code_name => CommonErrorCode::REQUEST_PARAMS_ERROR,
$message_name => $is_testing ? $throwable->getMessage() : CommonErrorCode::getMessage(
CommonErrorCode::SERVER_ERROR
),
];
$status_code = RFC4918::UNPROCESSABLE_ENTITY;
}
if ($throwable instanceof ValidationException) {
$data = $throwable->validator->errors()->first();
if (is_numeric($data)) {
$code = (int) $data;
$code = (int)$data;
$data = CommonErrorCode::getMessage($code);
}
$data = [$code_name => $code ?? CommonErrorCode::REQUEST_PARAMS_ERROR, $message_name => $data];
$status_code = RFC4918::UNPROCESSABLE_ENTITY;
}
if ($throwable instanceof ValidateException) {
$status_code = RFC4918::UNPROCESSABLE_ENTITY;
$code = $throwable->getCode();
$message = $throwable->getMessage();
$data = [$code_name => $code, $message_name => empty($message) ? CommonErrorCode::getMessage($code, ['param' => $throwable->getFieldName()]) : $message];
$data = [
$code_name => $code,
$message_name => empty($message)
? CommonErrorCode::getMessage(
$code,
[
'param' => $throwable->getFieldName(),
]
)
: $message,
];
if ($is_debug) {
$data['currentValue'] = $throwable->getCurrentValue();
$data['availableValue'] = $throwable->getAvailableValue();
@@ -116,14 +151,15 @@ class CommonHandler extends ExceptionHandler
if ($throwable instanceof NotFoundHttpException) {
$code = CommonErrorCode::ROUTE_NOT_FOUND;
$data = [$code_name => $code, $message_name => CommonErrorCode::getMessage($code)];
$status_code = 404;
$status_code = RFC7231::NOT_FOUND;
}
// 模型不存在
if ($throwable instanceof ModelNotFoundException) {
$code = empty($throwable->getCode()) ? CommonErrorCode::MODEL_NOT_FOUND : $throwable->getCode();
$message = empty($throwable->getCode()) ? CommonErrorCode::getMessage($code, ['resource' => '资源']) : $throwable->getMessage();
$message = empty($throwable->getCode()) ? CommonErrorCode::getMessage($code, ['resource' => '资源']
) : $throwable->getMessage();
$data = [$code_name => $code, $message_name => $message];
$status_code = 404;
$status_code = RFC7231::NOT_FOUND;
}
// 300 服务出错
// 303 缓存异常
@@ -132,7 +168,12 @@ class CommonHandler extends ExceptionHandler
if ($throwable->getMessage() === 'Connection refused') {
$code = CommonErrorCode::SERVER_CACHE_REDIS_REFUSED_ERROR;
}
$data = [$code_name => $code, $message_name => CommonErrorCode::getMessage($is_testing ? $code : CommonErrorCode::SERVER_CACHE_REDIS_ERROR)];
$data = [
$code_name => $code,
$message_name => CommonErrorCode::getMessage(
$is_testing ? $code : CommonErrorCode::SERVER_CACHE_REDIS_ERROR
),
];
}
// 306 消息异常
// 30601 邮箱发件异常
@@ -141,14 +182,29 @@ class CommonHandler extends ExceptionHandler
if (strpos($throwable->getMessage(), '500 Error: bad syntax')) {
$code = CommonErrorCode::SERVER_MESSAGE_EMAIL_NOT_FOUND;
}
$data = [$code_name => $code, $message_name => CommonErrorCode::getMessage($is_testing ? $code : CommonErrorCode::SERVER_MESSAGE_EMAIL_ERROR)];
$data = [
$code_name => $code,
$message_name => CommonErrorCode::getMessage(
$is_testing ? $code : CommonErrorCode::SERVER_MESSAGE_EMAIL_ERROR
),
];
}
if (empty($data)) {
// 其他情况
$data = [$code_name => $is_testing ? $throwable->getCode() == 0 ? CommonErrorCode::SERVER_ERROR : $throwable->getCode() : CommonErrorCode::SERVER_ERROR, $message_name => $is_testing ? $throwable->getMessage() : __(CommonErrorCode::getMessage(CommonErrorCode::SERVER_ERROR))];
$data = [
$code_name => $is_testing ? $throwable->getCode(
) == 0 ? CommonErrorCode::SERVER_ERROR : $throwable->getCode() : CommonErrorCode::SERVER_ERROR,
$message_name => $is_testing ? $throwable->getMessage() : __(
CommonErrorCode::getMessage(CommonErrorCode::SERVER_ERROR)
),
];
// 其他错误
if ($throwable instanceof HttpException) {
$data = [$code_name => $throwable->getCode() ?: $throwable->getStatusCode(), $message_name => $throwable->getMessage()];
$data = [
$code_name => $throwable->getCode() ?: $throwable->getStatusCode(),
$message_name => $throwable->getMessage(),
];
$status_code = $throwable->getStatusCode();
}
}
$response = $response->withHeader(Header::CONTENT_TYPE, 'application/json; charset=utf-8');
@@ -159,7 +215,7 @@ class CommonHandler extends ExceptionHandler
$this->logger->error(
<<<ERROR_LOG
TYPE: {$error_type}
[{$data[$code_name]}] {$data[$message_name]}
[$data[$code_name]] $data[$message_name]
{$throwable->getMessage()}
-------------------------------
REQUEST_TIME: {$request_time}
@@ -189,11 +245,14 @@ TRACE:
ERROR_LOG
);
$data = Json::encode($data);
if ($restful) {
$response = $response->withStatus($status_code ?? $throwable->status ?? $throwable->statusCode ?? RFC7231::INTERNAL_SERVER_ERROR);
if ($restful === ApiStyleService::RESTFUL) {
$response = $response->withStatus(
$status_code ?? $throwable->status ?? $throwable->statusCode ?? RFC7231::INTERNAL_SERVER_ERROR
);
}
return $response->withBody(new SwooleStream($data));
}
/**
* 判断该异常处理器是否要对该异常进行处理.
*/

View File

@@ -0,0 +1,34 @@
<?php
/**
* AbstractListener.php@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/1/16
*/
namespace Singularity\HDK\Core\Listener;
use Hyperf\Contract\ContainerInterface;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Event\Contract\ListenerInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
abstract class AbstractListener implements ListenerInterface
{
#[Inject]
protected ContainerInterface $container;
protected StdoutLoggerInterface $stdoutLogger;
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function __construct()
{
$this->stdoutLogger = $this->container->get(StdoutLoggerInterface::class);
}
}

View File

@@ -0,0 +1,94 @@
<?php
/**
* EmailWillSentListener.php@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/1/16
*/
namespace Singularity\HDK\Core\Listener;
use Hyperf\Contract\ContainerInterface;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Event\Contract\ListenerInterface;
use JetBrains\PhpStorm\NoReturn;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Singularity\HDK\Core\Constants\CommonErrorCode;
use Singularity\HDK\Core\Events\EmailWillSent;
use Singularity\HDK\Core\Service\EmailService;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
/**
* Singularity\HDK\Core\Listener\EmailWillSentListener@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/1/16
*
* @link ../../docs/Email.md
*/
class EmailWillSentListener implements ListenerInterface
{
#[Inject]
private ContainerInterface $container;
/**
* @inheritDoc
*/
public function listen(): array
{
return [
EmailWillSent::class,
];
}
/**
* @param EmailWillSent $event
* @return void
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
#[NoReturn]
public function process(object $event): void
{
$stdoutLogger = $this->container->get(StdoutLoggerInterface::class);
$emailService = $this->container->get(EmailService::class);
try {
$event->type === 'html'
? $emailService->sendHtml(
target: $event->target,
subject: $event->subject,
html: $event->content,
cc: $event->cc
)
: $emailService->sendText(
target: $event->target,
subject: $event->subject,
text: $event->content,
cc: $event->cc
);
$stdoutLogger->info('邮件发送成功!');
$stdoutLogger->info("To: $event->target");
$stdoutLogger->info("Subject: $event->subject");
$stdoutLogger->debug('Content: ');
$stdoutLogger->debug($event->content);
} catch (TransportExceptionInterface $e) {
$code = CommonErrorCode::SERVER_MESSAGE_EMAIL_ERROR;
$msg = $e->getMessage();
if (strpos($msg, '500 Error: bad syntax')) {
$code = CommonErrorCode::SERVER_MESSAGE_EMAIL_NOT_FOUND;
$msg = CommonErrorCode::getMessage($code);
}
$stdoutLogger->alert('邮件发送失败!');
$stdoutLogger->error(
<<<ERROR_LOG
[$code] $msg
ERROR_LOG
);
}
}
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* SmsWillSentListener.php@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/1/16
*/
namespace Singularity\HDK\Core\Listener;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Singularity\HDK\Core\Events\SmsWillSent;
use Singularity\HDK\Core\Service\SmsService;
use Throwable;
/**
* Singularity\HDK\Core\Listener\SmsWillSentListener@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/1/16
*/
class SmsWillSentListener extends AbstractListener
{
/**
* @inheritDoc
*/
public function listen(): array
{
return [
SmsWillSent::class,
];
}
/**
* @param SmsWillSent $event
* @return void
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function process(object $event): void
{
$smsService = $this->container->get(SmsService::class);
try {
$smsService->sendSmsCountryside(
phone: $event->phone,
templateCode: $event->templateCode,
templateParam: $event->templateParam,
signName: $event->signName
);
} catch (Throwable $throwable) {
$code = $throwable->getCode();
$message = $throwable->getMessage();
$this->stdoutLogger->alert('短信发送失败!');
$this->stdoutLogger->error(sprintf("[%u] %s", $code, $message));
}
}
}

View File

@@ -10,24 +10,29 @@
namespace Singularity\HDK\Core\Middleware;
use Hyperf\Codec\Json;
use Hyperf\Contract\Arrayable;
use Hyperf\Contract\Jsonable;
use Hyperf\Contract\LengthAwarePaginatorInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpServer\CoreMiddleware;
use Hyperf\Utils\Codec\Json;
use Lmc\HttpConstants\Header;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Singularity\HDK\Core\Service\UtilsService;
use function Hyperf\Config\config;
/**
* Singularity\HDK\Utils\Middleware\ClassicCoreMiddleware@hyperf-development-kit
*
* @author 李东云<dongyun.li@luxcreo.cn>
* Powered by PhpStorm
* Created on 2022/4/29
*
* @deprecated
* @see CommonCoreMiddleware
*/
class ClassicCoreMiddleware extends CoreMiddleware
{

View File

@@ -0,0 +1,32 @@
<?php
/**
* ClassicStyleMiddleware.php@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/3/10
*/
namespace Singularity\HDK\Core\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Singularity\HDK\Core\Service\ApiStyleService;
class ClassicStyleMiddleware implements MiddlewareInterface
{
public function __construct(protected ApiStyleService $apiStyleService)
{
}
/**
* @inheritDoc
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->apiStyleService->set(ApiStyleService::CLASSIC);
return $handler->handle($request);
}
}

View File

@@ -0,0 +1,160 @@
<?php
/**
* ClassicCoreMiddleware.php@hyperf-development-kit
*
* @author 李东云<dongyun.li@luxcreo.cn>
* Powered by PhpStorm
* Created on 2022/4/29
*/
namespace Singularity\HDK\Core\Middleware;
use Hyperf\Codec\Json;
use Hyperf\Contract\Arrayable;
use Hyperf\Contract\Jsonable;
use Hyperf\Contract\LengthAwarePaginatorInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpServer\CoreMiddleware;
use Lmc\HttpConstants\Header;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Singularity\HDK\Core\Service\ApiStyleService;
use Singularity\HDK\Core\Service\UtilsService;
use function Hyperf\Config\config;
/**
* Singularity\HDK\Core\Middleware\CommonCoreMiddleware@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/3/10
*/
class CommonCoreMiddleware extends CoreMiddleware
{
#[Inject]
private UtilsService $utilsService;
#[Inject]
private ApiStyleService $apiStyleService;
/**
* @inheritDoc
*/
protected function transferToResponse($response, ServerRequestInterface $request): ResponseInterface
{
$style = $this->apiStyleService->get();
if ($style === ApiStyleService::RESTFUL) {
return $this->transferToRestfulResponse($response, $request);
} else {
return $this->transferToClassicResponse($response, $request);
}
}
/**
* @param array|string|Arrayable|Jsonable|null $response
* @param ServerRequestInterface $request
* @return ResponseInterface
*/
protected function transferToRestfulResponse(Arrayable|Jsonable|array|string|null $response, ServerRequestInterface $request): ResponseInterface
{
// 分页数据
if ($response instanceof LengthAwarePaginatorInterface) {
$fact_response = $this->response()
->withHeader('Per-Page', (string)$response->perPage())
->withHeader('Total', (string)$response->total())
->withHeader('Current-Page', (string)$response->currentPage())
->withHeader('Total-Pages', (string)$response->hasPages());
$fact_response = $this->utilsService->extendLinkToHeader($fact_response, $response->nextPageUrl(), 'next');
$fact_response = $this->utilsService->extendLinkToHeader(
$fact_response,
$response->url($response->lastPage()),
'last'
);
$fact_response = $this->utilsService->extendLinkToHeader($fact_response, $response->url(1), 'first');
$fact_response = $this->utilsService->extendLinkToHeader(
$fact_response,
$response->previousPageUrl(),
'prev'
);
return $fact_response->withBody(new SwooleStream(Json::encode($response->items())));
}
return parent::transferToResponse($response, $request);
}
/**
* @param array|string|Arrayable|Jsonable|null $response
* @param ServerRequestInterface $request
* @return ResponseInterface
*/
protected function transferToClassicResponse(
Arrayable|Jsonable|array|string|null $response,
ServerRequestInterface $request
): ResponseInterface {
$code_name = config('common.response.code_name');
$message_name = config('common.response.message_name');
$data_name = config('common.response.data_name');
// 分页数据
if ($response instanceof LengthAwarePaginatorInterface) {
$paginator = $response;
$fact_response = $this->response()->withHeader('Per-Page', (string)$paginator->perPage())->withHeader(
'Total',
(string)$paginator->total()
)->withHeader('Current-Page', (string)$paginator->currentPage())->withHeader(
'Total-Pages',
(string)$paginator->hasPages()
);
$fact_response = $this->utilsService->extendLinkToHeader($fact_response, $paginator->nextPageUrl(), 'next');
$fact_response = $this->utilsService->extendLinkToHeader(
$fact_response,
$paginator->url($paginator->lastPage()),
'last'
);
$fact_response = $this->utilsService->extendLinkToHeader($fact_response, $paginator->url(1), 'first');
$fact_response = $this->utilsService->extendLinkToHeader(
$fact_response,
$paginator->previousPageUrl(),
'prev'
);
return $fact_response->withAddedHeader(Header::CONTENT_TYPE, 'application/json')->withBody(
new SwooleStream(
Json::encode(
[
$code_name => 200,
$message_name => 'ok',
$data_name => $response->items(),
'meta' => [
'currentPage' => $paginator->currentPage(),
'lastPage' => $paginator->lastPage(),
'perPage' => $paginator->perPage(),
'total' => $paginator->total(),
],
]
)
)
);
}
// 普通数组
if (is_array($response) || $response instanceof Arrayable) {
$response = [$code_name => 200, $message_name => 'ok', $data_name => $response];
return $this->response()->withAddedHeader(Header::CONTENT_TYPE, 'application/json')->withBody(
new SwooleStream(Json::encode($response))
);
}
// 可 Json 化的数据结构
if ($response instanceof Jsonable) {
$response = [$code_name => 200, $message_name => 'ok', $data_name => Json::decode((string)$response)];
return $this->response()->withAddedHeader(Header::CONTENT_TYPE, 'application/json')->withBody(
new SwooleStream(Json::encode($response))
);
}
// 其他默认按字符串处理
return $this->response()->withAddedHeader(Header::CONTENT_TYPE, 'text/plain')->withBody(
new SwooleStream((string)$response)
);
}
}

View File

@@ -7,10 +7,14 @@ namespace Singularity\HDK\Core\Middleware;
use Hyperf\Context\Context;
use Hyperf\Contract\TranslatorInterface;
use Hyperf\Di\Annotation\Inject;
use Lmc\HttpConstants\Header;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Symfony\Component\HttpFoundation\Request;
use function Hyperf\Config\config;
/**
* Singularity\HDK\Utils\Middleware\InternationalizationMiddleware@HDK
@@ -26,13 +30,16 @@ class InternationalizationMiddleware implements MiddlewareInterface
*/
#[Inject]
private TranslatorInterface $translator;
/**
* @inheritDoc
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$response = Context::get(ResponseInterface::class);
$language = $request->getHeaderLine('Accept-Language');
$req = (new Request());
$req->headers->set(Header::ACCEPT_LANGUAGE, $request->getHeaderLine(Header::ACCEPT_LANGUAGE));
$language = $req->getPreferredLanguage();
if (!empty($language)) {
$language = match (strtolower($language)) {
'en', 'en_us', 'en-us', 'en-uk', 'en_uk' => 'en',
@@ -40,9 +47,14 @@ class InternationalizationMiddleware implements MiddlewareInterface
default => config('translation.locale'),
};
$this->translator->setLocale($language);
$response = $response->withAddedHeader('Content-Language', strtr($this->translator->getLocale(), '_', '-'));
Context::set(ResponseInterface::class, $response);
}
$response = Context::get(ResponseInterface::class);
$response = $response->withAddedHeader(
Header::CONTENT_LANGUAGE,
strtr($this->translator->getLocale(), '_', '-')
);
Context::set(ResponseInterface::class, $response);
return $handler->handle($request);
}
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* ClassicStyleMiddleware.php@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/3/10
*/
namespace Singularity\HDK\Core\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Singularity\HDK\Core\Service\ApiStyleService;
class RestStyleMiddleware implements MiddlewareInterface
{
public function __construct(protected ApiStyleService $apiStyleService)
{
}
/**
* @inheritDoc
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->apiStyleService->set(ApiStyleService::RESTFUL);
return $handler->handle($request);
}
}

View File

@@ -24,6 +24,9 @@ use Singularity\HDK\Core\Service\UtilsService;
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/1/14
*
* @deprecated
* @see CommonCoreMiddleware
*/
class RestfulCoreMiddleware extends CoreMiddleware
{

View File

@@ -0,0 +1,162 @@
<?php
/**
* SessionMiddleware.php@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/3/8
*/
namespace Singularity\HDK\Core\Middleware;
use Carbon\Carbon;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Contract\SessionInterface;
use Hyperf\HttpMessage\Cookie\Cookie;
use Hyperf\HttpMessage\Server\Response;
use Hyperf\Session\SessionManager;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
/**
* Singularity\HDK\Core\Middleware\SessionMiddleware@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/3/8
*
* @deprecated since 0.2.21, use \Singularity\HDK\Auth\Middleware\SessionMiddleware instead.
*/
class SessionMiddleware implements MiddlewareInterface
{
public function __construct(private SessionManager $sessionManager, private ConfigInterface $config)
{
}
/**
* Process an incoming server request.
* Processes an incoming server request in order to produce a response.
* If unable to produce the response itself, it may delegate to the provided
* request handler to do so.
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if (!$this->isSessionAvailable()) {
return $handler->handle($request);
}
$session = $this->sessionManager->start($request);
try {
$response = $handler->handle($request);
} finally {
$this->storeCurrentUrl($request, $session);
$session = $this->sessionManager->getSession();
/*
* 现在的机制,但凡写入 Redis 的数据,
* 过期时间就是固定的 gc_maxlifetime
*
* 而 RedisHandler 只会被依赖注入时加载一次,
* 后续无法临时修改 gc_maxlifetime
*
* 又因为现在没有其他情况用到 session
* 只有登录之后才会记下用户信息
*
* 所以一个妥协的方案,就是只有登录了再写入 Redis
*
* (除非重写整套 RedisHandler/RedisHandlerFactory/...
*/
if (!$this->auth($session)) {
$this->sessionManager->end($session);
}
}
return $this->addCookieToResponse($request, $response, $session);
}
private function isSessionAvailable(): bool
{
return $this->config->has('session.handler');
}
/**
* Store the current URL for the request if necessary.
*/
private function storeCurrentUrl(RequestInterface $request, SessionInterface $session)
{
if ($request->getMethod() === 'GET') {
$session->setPreviousUrl($this->fullUrl($request));
}
}
/**
* Add the session cookie to the response·.
*/
private function addCookieToResponse(
ServerRequestInterface $request,
ResponseInterface $response,
SessionInterface $session
): ResponseInterface {
$cookie = new Cookie(
name: $session->getName(),
value: $session->getId(),
expire: $this->getCookieExpirationDate($session),
path: $this->config->get('session.options.path', '/'),
domain: $this->config->get('session.options.domain', $request->getUri()->getHost()),
secure: $this->config->get(
'session.options.secure',
strtolower($request->getUri()->getScheme()) === 'https'
),
httpOnly: true,
sameSite: $this->config->get('session.options.samesite', Cookie::SAMESITE_LAX)
);
if (!method_exists($response, 'withCookie')) {
return $response->withHeader('Set-Cookie', (string)$cookie);
}
/* @var Response $response */
return $response->withCookie($cookie);
}
/**
* Get the full URL for the request.
*/
private function fullUrl(RequestInterface $request): string
{
$uri = $request->getUri();
$query = $uri->getQuery();
$question = $uri->getHost() . $uri->getPath() == '/' ? '/?' : '?';
return $query ? $this->url($request) . $question . $query : $this->url($request);
}
/**
* Get the session lifetime in seconds.
*/
private function getCookieExpirationDate(SessionInterface $session): int
{
// if ($this->config->get('session.options.expire_on_close')) {
if (!$this->auth($session)) {
$expirationDate = 0;
} else {
$expireSeconds = $this->config->get('session.options.cookie_lifetime', 5 * 60 * 60);
$expirationDate = Carbon::now()->addSeconds($expireSeconds)->getTimestamp();
}
return $expirationDate;
}
/**
* Get the URL (no query string) for the request.
*/
private function url(RequestInterface $request): string
{
return rtrim(preg_replace('/\?.*/', '', (string)$request->getUri()));
}
private function auth(SessionInterface $session)
{
return $session->has('userInfo');
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* ApiStyleService.php@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/3/10
*/
namespace Singularity\HDK\Core\Service;
use Hyperf\Context\Context;
use function Hyperf\Config\config;
class ApiStyleService
{
public const RESTFUL = 'restful';
public const CLASSIC = 'classic';
public function __construct()
{
Context::set(self::class, config('common.response.restful') ? self::RESTFUL : self::CLASSIC);
}
/**
* @param literal-string $style
* @return $this
*/
public function set(string $style): static
{
Context::set(self::class, $style === self::RESTFUL ? self::RESTFUL : self::CLASSIC);
return $this;
}
public function get(): string
{
return Context::get(self::class) ?? (config('common.response.restful')
? ApiStyleService::RESTFUL
: ApiStyleService::CLASSIC);
}
}

View File

@@ -18,6 +18,8 @@ use Symfony\Component\Mailer\Transport;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use function Hyperf\Config\config;
/**
* 邮箱验证码
*/

View File

@@ -10,6 +10,10 @@ use Psr\Http\Message\ServerRequestInterface;
*/
class ExtendService
{
public function __construct(private UtilsService $utils)
{
}
/**
* @param ServerRequestInterface|null $request
* @param array<string, string>|null $params
@@ -17,18 +21,16 @@ class ExtendService
*/
public function parse(
?ServerRequestInterface $request,
?array $params = null
array|string|null $params = null
): array {
$params ??= $request->getQueryParams();
$extends = $params['extends'] ?? null;
if (!empty($extends)) {
$extends = explode(',', $extends);
return Context::set(self::class, array_map('trim', $extends));
}
$params ??= $request?->getQueryParams();
$extends = explode(',', $params['extends'] ?? '');
$extends = array_map('trim', $extends);
return [];
return Context::set(self::class, array_filter($extends));
}
/**
* @return array<string, string>
*/
@@ -37,6 +39,12 @@ class ExtendService
return Context::get(self::class) ?? [];
}
public function hasExtends(): bool
{
$extends = Context::get(self::class);
return is_array($extends) && count($extends) > 0;
}
/**
* 判断是否传入了此扩展
*
@@ -44,8 +52,8 @@ class ExtendService
*
* @return bool
*/
public function hasExtends(string $field): bool
public function hasExtend(string $field): bool
{
return Context::has(self::class) && isset(array_flip(Context::get(self::class))[$field]);
return $this->utils->inArray($field, Context::get(self::class) ?? []);
}
}

View File

@@ -0,0 +1,101 @@
<?php
declare(strict_types=1);
namespace Singularity\HDK\Core\Service;
use Ergebnis\Http\Method;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Utils;
use Hyperf\Codec\Json;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Guzzle\ClientFactory;
use Psr\Http\Message\ResponseInterface;
/**
* 发起 Http 请求的类
*/
class HttpRequestService
{
// public const TIMEOUT = 20;
#[Inject]
private ClientFactory $client;
/**
* @var array<literal-string, mixed>
*/
private array $options = [];
/**
* @param string $url
* @param array<string, string|int> $params
* @param array $data
* @return ResponseInterface
* @throws GuzzleException
*/
public function requestGet(string $url, array $params = [], array $data = []): ResponseInterface
{
$request = new Request(Method\Rfc\Rfc7231::GET, $url);
return $this->getClient()->send($request, [
'query' => $params,
'json' => $data,
]);
}
private function getClient(): Client
{
return $this->client->create($this->options);
}
/**
* @param string $url
* @param array<string, mixed> $data
* @param array<string, string|int> $params
* @return ResponseInterface
* @throws GuzzleException
*/
public function requestPost(string $url, array $params = [], array $data = []): ResponseInterface
{
$data = Json::encode($data);
$request = new Request(
'post',
$url,
['Content-Type' => 'application/json'],
Utils::streamFor($data),
);
return $this->getClient()->send($request, [
'query' => $params,
]);
}
/**
* @param string $url
* @param array<string, mixed> $data
* @param array<string, string|int> $params
* @return ResponseInterface
* @throws GuzzleException
*/
public function requestPut(string $url, array $params = [], array $data = []): ResponseInterface
{
$data = Json::encode($data);
$request = new Request('put', $url, ['Content-Type' => 'application/json'], Utils::streamFor($data));
return $this->getClient()->send($request, [
'query' => $params,
]);
}
/**
* 定制 options
* @param array<string, mixed> $options
* @return $this
*/
public function setOptions(array $options): HttpRequestService
{
$this->options = array_replace_recursive($this->options, $options);
return $this;
}
}

View File

@@ -9,7 +9,9 @@
namespace Singularity\HDK\Core\Service;
use Hyperf\Utils\Codec\Json;
use Hyperf\Codec\Json;
use function Hyperf\Config\config;
class OssService
{

View File

@@ -6,10 +6,13 @@ use AlibabaCloud\SDK\Dysmsapi\V20170525\Dysmsapi;
use AlibabaCloud\SDK\Dysmsapi\V20170525\Models\SendSmsRequest;
use AlibabaCloud\Tea\Exception\TeaError;
use Darabonba\OpenApi\Models\Config;
use Hyperf\HttpMessage\Exception\HttpException;
use Hyperf\Utils\Codec\Json;
use Hyperf\Codec\Json;
use Hyperf\HttpMessage\Exception\ServerErrorHttpException;
use Singularity\HDK\Core\Constants\CommonErrorCode;
use Singularity\HDK\Core\Exceptions\ValidateException;
use UnexpectedValueException;
use function Hyperf\Config\config;
/**
* 短信服务
@@ -17,7 +20,7 @@ use Singularity\HDK\Core\Exceptions\ValidateException;
class SmsService
{
/**
* @var \AlibabaCloud\SDK\Dysmsapi\V20170525\Dysmsapi
* @var Dysmsapi
*/
private Dysmsapi $client;
@@ -29,7 +32,7 @@ class SmsService
/**
* 初始化实例
*
* @return \AlibabaCloud\SDK\Dysmsapi\V20170525\Dysmsapi
* @return Dysmsapi
*/
private function createClient(): Dysmsapi
{
@@ -44,13 +47,17 @@ class SmsService
/**
* 国内短信
*
* @param string $phone 接收短信的手机号码
* @param string|null $templateCode 短信模板CODE
* @param array<string, string>|null $templateParam 短信模板变量对应的实际值(不支持空数组)
* @param string|null $signName 短信签名名称
* @param string $phone 接收短信的手机号码
* @param string|null $templateCode 短信模板CODE
* @param array<string, string>|null $templateParam 短信模板变量对应的实际值(不支持空数组)
* @param string|null $signName 短信签名名称
*
* @return bool
* @throws UnexpectedValueException 参数校验
* @throws ValidateException 频率太高
* @throws ServerErrorHttpException 阿里云短信服务报错
* @link https://help.aliyun.com/document_detail/419273.htm
*
*/
public function sendSmsCountryside(
string $phone,
@@ -59,7 +66,7 @@ class SmsService
?string $signName = null,
): bool {
if (is_array($templateParam) && count($templateParam) <= 0) {
throw new \UnexpectedValueException('不支持空数组,请用 null 代替或不传', CommonErrorCode::FORMATTER_ERROR);
throw new UnexpectedValueException('不支持空数组,请用 null 代替或不传', CommonErrorCode::FORMATTER_ERROR);
}
$phone_number = strtr($phone, ['#' => '']);
@@ -101,11 +108,10 @@ class SmsService
}
}
throw new HttpException(
500,
$message,
CommonErrorCode::SERVER_DEPENDENCY_SMS_ERROR,
$error
throw new ServerErrorHttpException(
message: $message,
code: CommonErrorCode::SERVER_DEPENDENCY_SMS_ERROR,
previous: $error
);
}

View File

@@ -8,7 +8,6 @@ use Closure;
use Exception;
use Generator;
use Hyperf\HttpServer\Contract\RequestInterface;
use JetBrains\PhpStorm\NoReturn;
use JetBrains\PhpStorm\Pure;
use Psr\Http\Message\ResponseInterface;
@@ -236,7 +235,6 @@ class UtilsService
*
* @return void
*/
#[NoReturn]
public function unlimitedSubCategoriesQuicklyWithLevel(
array &$list,
int $level = 1,
@@ -328,4 +326,17 @@ class UtilsService
'unit' => $unitToUpper ? strtoupper($unit[$i]) : $unit[$i],
];
}
/**
* 更快的判断数组元素方法
* @param float|int|string $needle
* @param array<int, mixed> $haystack
* @return bool
*/
public function inArray(float|int|string $needle, array $haystack): bool
{
$list = array_flip($haystack);
return isset($list[$needle]);
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* XmlService.php@LuxOP
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/4/10
*/
namespace Singularity\HDK\Core\Service;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
class XmlService
{
private XmlEncoder $service;
public function __construct(XmlEncoder $encoder)
{
$this->service = $encoder;
}
/**
* @param object|array<string, mixed> $data
* @param string $xmlRootNodeName
* @param bool $xmlFormatOutput 是否格式化
* @param string $xmlVersion
* @param string $xmlEncoding
* @param bool $xmlStandalone 是否添加声明规范的标签到xml
* @param int[] $encoderIgnoredNodeTypes
* @param bool $removeEmptyTags
* @return false|string
* @see https://symfony.com/doc/current/components/serializer.html#the-xmlencoder
*/
public function encode(
object|array $data,
string $xmlRootNodeName = 'root',
bool $xmlFormatOutput = true,
string $xmlVersion = '1.0',
string $xmlEncoding = 'utf-8',
bool $xmlStandalone = false,
array $encoderIgnoredNodeTypes = [],
bool $removeEmptyTags = false,
): false|string {
return $this->service->encode(
$data,
XmlEncoder::FORMAT,
[
XmlEncoder::ENCODER_IGNORED_NODE_TYPES => $encoderIgnoredNodeTypes,
XmlEncoder::ROOT_NODE_NAME => $xmlRootNodeName,
XmlEncoder::FORMAT_OUTPUT => $xmlFormatOutput,
XmlEncoder::VERSION => $xmlVersion,
XmlEncoder::ENCODING => $xmlEncoding,
XmlEncoder::STANDALONE => $xmlStandalone,
XmlEncoder::REMOVE_EMPTY_TAGS => $removeEmptyTags,
]
);
}
/**
* @param string $xml
* @param bool $xmlTypeCastAttributes 是否自动转换类型
* @param bool $asCollection 是否全部使用数组
* @param int[] $decoderIgnoredNodeTypes
* @param int $loadOptions
* @return array<string, mixed>
*/
public function decode(
string $xml,
bool $xmlTypeCastAttributes = true,
bool $asCollection = false,
array $decoderIgnoredNodeTypes = [XML_PI_NODE, XML_COMMENT_NODE],
int $loadOptions = LIBXML_NONET | LIBXML_NOBLANKS,
): array {
return $this->service->decode(
$xml,
XmlEncoder::FORMAT,
[
XmlEncoder::LOAD_OPTIONS => $loadOptions,
XmlEncoder::DECODER_IGNORED_NODE_TYPES => $decoderIgnoredNodeTypes,
XmlEncoder::TYPE_CAST_ATTRIBUTES => $xmlTypeCastAttributes,
XmlEncoder::AS_COLLECTION => $asCollection,
]
);
}
}

View File

@@ -0,0 +1,78 @@
<?php
/**
* Paginatable.php@Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/7/18
*/
namespace Singularity\HDK\Core\Traits;
use Closure;
use Hyperf\Contract\LengthAwarePaginatorInterface;
use Hyperf\Database\Model\Builder;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Stringable\Str;
use Singularity\HDK\Core\Service\ExtendService;
trait RestfulList
{
#[Inject]
protected ExtendService $extend;
#[Inject]
protected RequestInterface $request;
protected function restSelect(Closure $callback, ?Closure $filter = null)
{
$options = [];
$result = $this->parseParameters(function ($query, $parsedOptions) use ($callback, &$options) {
$options = $parsedOptions;
$callback($query, $parsedOptions);
});
return $this->responseFormatter($options, $result, $filter);
}
protected function parseParameters(Closure $callback): mixed
{
$query = $this->request->getQueryParams();
$options = [
'size' => $this->request->query('size'),
'page' => $this->request->query('page'),
'order' => $this->request->query('order', 'created_at'),
'sort' => $this->request->query('sort', 'desc'),
'group' => $this->request->query('group'),
'extends' => $this->extend->getExtends(),
];
unset($query['sort'], $query['page'], $query['size'], $query['order'], $query['group'], $query['extends']);
return $callback(query: $query, options: $options);
}
protected function responseFormatter(
array $options,
Builder $builder,
?Closure $filter = null
) {
$perPage = $options['size'] ?? null;
$order = $options['order'] ?? 'created_at';
$sort = $options['sort'] ?? 'desc';
$pagination = !!($options['page'] ?? $perPage ?? false);
// $group = $options['group'] ?? null;
$builder = $builder->orderBy(Str::snake($order), $sort);
$result = $pagination ? $builder->paginate($perPage) : $builder->get();
if (is_null($filter)) {
return $result;
}
if ($result instanceof LengthAwarePaginatorInterface) {
$collection = $result->getCollection();
$collection = $filter($collection);
return $result->setCollection($collection);
}
return $filter($result);
}
}

View File

@@ -12,9 +12,9 @@ namespace Singularity\HDK\Test\Core\Service;
use Singularity\HDK\Core\Service\EmailService;
use Symfony\Component\Mailer\Exception\TransportException;
$dsn = 'smtp://account@luxcreo.ai:Qfsd8866@smtp.qiye.aliyun.com:465';
$dsn = 'smtp://account@luxcreo.com:Qfsd8866@smtp-mail.outlook.com:587';
$mail_sender_name = 'LuxCreo';
$mail_sender = 'account@luxcreo.ai';
$mail_sender = 'account@LuxCreo.com';
$email = new EmailService($dsn, $mail_sender_name, $mail_sender);
it('assertions that send HTML is available', function () use ($email) {
@@ -26,7 +26,7 @@ it('assertions that send HTML is available', function () use ($email) {
HTML
);
expect($result)->toBeTrue();
});
})->only();
it('assertions that send Text is available', function () use ($email) {
$result = $email->sendText(

View File

@@ -9,30 +9,59 @@
namespace Singularity\HDK\Test\Core\Unit;
use Hyperf\Context\Context;
use Singularity\HDK\Core\Service\ExtendService;
use Singularity\HDK\Core\Service\UtilsService;
$service = new ExtendService();
/** @var ExtendService $service */
$service = make(ExtendService::class, ['utils' => new UtilsService()]);
it('asserts no parameters can be parsed.', function (ExtendService $service, $params) {
$service->parse(
null,
$params
);
$result = $service->getExtends();
expect($result)->toBeArray()->toBe([])->toHaveCount(0)->toBe([]);
})->with([
[$service, null],
[$service, ''],
[$service, []],
[$service, ['extends' => '']],
[$service, ['extends' => null]],
]);
it('asserts has no specify extend', function () use ($service) {
Context::destroy(ExtendService::class);
expect($service->hasExtend('a'))->toBeFalse();
})->depends('it asserts query parameters can be parsed.');
it('asserts query parameters can be parsed.', function () use ($service) {
$result = $service->parse(
null,
params: [
[
'id' => 5,
'extends' => 'a,b',
]
);
expect($result)->toBeArray()->toHaveCount(2)->toBe(['a', 'b']);
});
it('asserts has extends', function () use ($service) {
expect($service->hasExtends('a'))->toBeTrue()
->and($service->hasExtends('b'))->toBeTrue()
->and($service->hasExtends('c'))->toBeFalse();
Context::set(ExtendService::class, ['a', 'b']);
expect($service->hasExtends())->toBeTrue();
});
it('asserts has specify extend', function () use ($service) {
Context::set(ExtendService::class, ['a', 'b']);
expect($service->hasExtend('a'))->toBeTrue()
->and($service->hasExtend('b'))->toBeTrue()
->and($service->hasExtend('c'))->toBeFalse();
})->depends('it asserts query parameters can be parsed.');
it('asserts parsed extends', function () use ($service) {
$extends = $service->getExtends();
expect($extends)->toBeArray()->toMatchArray([
'a',
'b',
]);
})->depends('it asserts query parameters can be parsed.');
// it('asserts parsed extends', function () use ($service) {
// $extends = $service->getExtends();
// expect($extends)->toBeArray()->toMatchArray([
// 'a',
// 'b',
// ]);
// })->depends('it asserts query parameters can be parsed.');

View File

@@ -7,7 +7,7 @@
* Created on 2023/1/9
*/
use Hyperf\Utils\Codec\Json;
use Hyperf\Codec\Json;
use Singularity\HDK\Core\Service\OssService;
use function Spatie\PestPluginTestTime\testTime;

View File

@@ -60,3 +60,22 @@ test('断言可以根据参数构建 URL', function (string $url, array $params,
'http://username:password@127.0.0.1/git/resp?id=1#/page?a=b&c=d',
]
])->group('pure', 'utils');
test('断言可以判断是否是数组中的元素', function (
$needle,
array $haystack,
bool $expect,
bool $exceptions = false
) use ($utils) {
try {
expect($utils->inArray($needle, $haystack))->toBe($expect);
} catch (Throwable $e) {
if ($exceptions) {
expect(true)->toBeTrue();
}
}
})->with([
[1, ['1', 2, 3], true, false],
['1', ['1', 2, 3], true, false],
[[1, 2, 3], ['1', 2, 3], false, true],
])->group('pure', 'utils');

View File

@@ -0,0 +1,130 @@
<?php
/**
* XmlServiceTest.php@LuxOP
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/4/10
*/
namespace HyperfTest\Unit\Common;
use Singularity\HDK\Core\Service\XmlService;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use function Hyperf\Support\make;
/** @var XmlService $service */
$service = make(
XmlService::class,
['encoder' => make(XmlEncoder::class)]
);
test(
'assert Xml can be encoded',
function (array $data, string $expect, string $rootNodeName) use ($service) {
$result = $service->encode($data, $rootNodeName);
expect($result)->toBe($expect);
}
)->with([
'normal' => [
'data' => [
'@version' => '1.0',
'@descripe' => 'Luxcreo',
'UserName' => 'zhm',
'Email' => 'haimei.zheng@luxcreo.ai',
'BiosId' => '420036H32020120279',
'validTime' => '2099/03/27',
],
'expect' => <<<'XML'
<?xml version="1.0" encoding="utf-8"?>
<ClientInfo version="1.0" descripe="Luxcreo">
<UserName>zhm</UserName>
<Email>haimei.zheng@luxcreo.ai</Email>
<BiosId>420036H32020120279</BiosId>
<validTime>2099/03/27</validTime>
</ClientInfo>
XML,
'xmlRootNodeName' => 'ClientInfo',
],
'normal attribute' => [
'data' => [
'@version' => '1.0',
'@descripe' => 'Luxcreo',
'UserName' => 'zhm',
'Email' => [
'@type' => 'Business',
'#' => 'haimei.zheng@luxcreo.ai',
],
'BiosId' => '420036H32020120279',
'validTime' => '2099/03/27',
],
'expect' => <<<'XML'
<?xml version="1.0" encoding="utf-8"?>
<ClientInfo version="1.0" descripe="Luxcreo">
<UserName>zhm</UserName>
<Email type="Business">haimei.zheng@luxcreo.ai</Email>
<BiosId>420036H32020120279</BiosId>
<validTime>2099/03/27</validTime>
</ClientInfo>
XML
,
'ClientInfo',
],
'normal comment' => [
'data' => [
'@version' => '1.0',
'@descripe' => 'Luxcreo',
'UserName' => 'zhm',
'Email' => [
'@type' => 'Business',
'#' => 'haimei.zheng@luxcreo.ai',
],
'BiosId' => '420036H32020120279',
'validTime' => [
'#comment' => '到期时间',
],
],
'expect' => <<<'XML'
<?xml version="1.0" encoding="utf-8"?>
<ClientInfo version="1.0" descripe="Luxcreo">
<UserName>zhm</UserName>
<Email type="Business">haimei.zheng@luxcreo.ai</Email>
<BiosId>420036H32020120279</BiosId>
<validTime>
<!--到期时间-->
</validTime>
</ClientInfo>
XML
,
'ClientInfo',
],
]);
test('assert Xml can be parsed', function (string $xml, array $expected) use ($service) {
$data = $service->decode($xml);
expect($data)->toBe($expected);
})->with([
'normal' => [
'xml' => <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<ClientInfo version="1.0" descripe="LuxAlignAuthentication">
<UserName>zhm</UserName>
<Email>haimei.zheng@luxcreo.ai</Email>
<BiosId>420036H32020120279</BiosId>
</ClientInfo>
XML,
'expected' => [
'@version' => 1.0,
'@descripe' => 'LuxAlignAuthentication',
'UserName' => 'zhm',
'Email' => 'haimei.zheng@luxcreo.ai',
'BiosId' => '420036H32020120279',
],
],
]);

28
tests/prepend.php Normal file
View File

@@ -0,0 +1,28 @@
<?php
/**
* prepend.php@Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/8/29
*/
declare(strict_types=1);
use Hyperf\Context\ApplicationContext;
use Hyperf\Di\ClassLoader;
use Hyperf\Di\Container;
use Hyperf\Di\Definition\DefinitionSourceFactory;
require_once __DIR__ . '/../vendor/autoload.php';
defined('BASE_PATH') or define('BASE_PATH', dirname(__DIR__, 1));
(function () {
ClassLoader::init();
ApplicationContext::setContainer(
new Container((new DefinitionSourceFactory())())
);
// $container->get(Hyperf\Contract\ApplicationInterface::class);
})();