2.0 升级指南

2.0 版本新增了不少强大的功能,如果您已经投入了业务使用的项目且是基于官方提供的 Skeleton 项目创建的 1.1 版本的应用项目,那么可以根据下面的内容点来调整您的 Skeleton 项目,如果您是一个新的项目,按照文档通过 composer create-project hyperf/hyperf-skeleton 命令创建新的项目即可使用新的 2.0 版本的 skeleton 代码,如果您当前使用的版本是低于 1.1 的版本,那么需要您先升级到 1.1 后再根据此升级指南升级到 2.0 版本。

升级 Swoole 到 4.5+

2.0 版本将最低的 Swoole 版本要求从 4.4+ 提升到了 4.5+,这两个版本之间有一些使用上的细节差异,Hyperf 在较早的版本便已适配了这里版本差异,您可无需理会这里的差异细节,提升 Swoole 版本到 4.5+ 主要是减少历史包袱对 Hyperf 造成的长期影响。您可通过执行 php --ri swoole 来查看当前环境中的 Swoole 版本,您可根据 Swoole 文档 的指引来完成对 Swoole 的升级。

入口文件添加 ClassLoader 初始化

2.0 改变了 AOP 的底层逻辑,所以需要您在框架入口文件 bin/hyperf.php 中添加一行初始化的代码,您需要在入口匿名函数内的第一行添加代码 Hyperf\Di\ClassLoader::init();,如下所示:

  1. <?php
  2. ini_set('display_errors', 'on');
  3. ini_set('display_startup_errors', 'on');
  4. error_reporting(E_ALL);
  5. date_default_timezone_set('Asia/Shanghai');
  6. ! defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 1));
  7. ! defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL);
  8. require BASE_PATH . '/vendor/autoload.php';
  9. // Self-called anonymous function that creates its own scope and keep the global namespace clean.
  10. (function () {
  11. Hyperf\Di\ClassLoader::init();
  12. /** @var \Psr\Container\ContainerInterface $container */
  13. $container = require BASE_PATH . '/config/container.php';
  14. $application = $container->get(\Hyperf\Contract\ApplicationInterface::class);
  15. $application->run();
  16. })();

与此同时,PHPUnit 的入口文件也许做同样的处理,文件位于 tests/bootstrap.php,如下所示:

  1. <?php
  2. declare(strict_types=1);
  3. error_reporting(E_ALL);
  4. date_default_timezone_set('Asia/Shanghai');
  5. ! defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 1));
  6. ! defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL);
  7. Swoole\Runtime::enableCoroutine(true);
  8. require BASE_PATH . '/vendor/autoload.php';
  9. Hyperf\Di\ClassLoader::init();
  10. $container = require BASE_PATH . '/config/container.php';
  11. $container->get(Hyperf\Contract\ApplicationInterface::class);

调整 composer.json

因为 2.0 版本 AOP 底层逻辑的调整,故移除了 init-proxy.sh 脚本,所以需要您从 composer.json 中去掉 scripts.post-autoload-dump 内的 "init-proxy.sh" 执行语句,并修改 post-autoload-dump 内的命令为 rm -rf runtime/container 语句。

  1. {
  2. "scripts": {
  3. "post-root-package-install": [
  4. "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
  5. ],
  6. "post-autoload-dump": [
  7. "rm -rf runtime/container"
  8. ],
  9. "analyse": "phpstan analyse --memory-limit 300M -l 0 -c phpstan.neon ./app ./config",
  10. "cs-fix": "php-cs-fixer fix $1",
  11. "start": "php ./bin/hyperf.php start",
  12. "test": "co-phpunit -c phpunit.xml --colors=always"
  13. }
  14. }

调整 Dockerfile

在 Docker 镜像的打包过程中,主动执行 php bin/hyperf.php 命令会帮助提前创建所有需要生成的代理类和注解扫描缓存,这样在生产环境运行启动时便无需再次的扫描,这样可以极大的优化生产环境启动的时间和内存使用量。以下示例不包含未修改的 Dockerfile 代码。

  1. ENV TIMEZONE=${timezone:-"Asia/Shanghai"} \
  2. APP_ENV=prod \
  3. SCAN_CACHEABLE=(true)
  4. COPY . /opt/www
  5. RUN composer install --no-dev -o && php bin/hyperf.php
  6. EXPOSE 9501
  7. ENTRYPOINT ["php", "/opt/www/bin/hyperf.php", "start"]

Docker 部署的用户,需要注意的是,在重新启动服务之前,最好先执行一次 php bin/hyperf.php 后再重新启动服务,以减少重新启动时的耗时。

调整 config/config.php 配置文件

您需要在 config/config.php 配置中添加 app_envscan_cacheable 两个配置项,下面的代码示例不包含其它无关的配置内容,如下所示:

  1. <?php
  2. return [
  3. // 生产环境使用 prod 值
  4. 'app_env' => env('APP_ENV', 'dev'),
  5. // 是否使用注解扫描缓存
  6. 'scan_cacheable' => env('SCAN_CACHEABLE', false),
  7. ];

scan_cacheable 配置用于控制应用启动时是否使用注解扫描缓存,以上 Dockerfileconfig/config.php 中都有相关的修改。当这个配置的值为 true 时,项目启动时则会认为所有类都已经完成了扫描并正确生成了对应的缓存和代理,则会跳过扫描阶段以便优化启动时间和减少内存开销。

修改 config/autoload/logger.php

因为 2.0 版本提高了对 Monolog 依赖的版本,在高版本的 Monolog 中,默认的日志格式发生了变化,如果对于日志的格式有要求,比如需要根据日志格式与日志系统对接等,可修改 config/autoload/logger.php 配置文件的 dateFormat 配置项,以保持与之前版本的一致。

  1. <?php
  2. declare(strict_types=1);
  3. return [
  4. 'default' => [
  5. 'handler' => [
  6. 'class' => Monolog\Handler\StreamHandler::class,
  7. 'constructor' => [
  8. 'stream' => BASE_PATH . '/runtime/logs/hyperf.log',
  9. 'level' => Monolog\Logger::DEBUG,
  10. ],
  11. ],
  12. 'formatter' => [
  13. 'class' => Monolog\Formatter\LineFormatter::class,
  14. 'constructor' => [
  15. 'format' => null,
  16. 'dateFormat' => 'Y-m-d H:i:s',
  17. 'allowInlineLineBreaks' => true,
  18. ],
  19. ],
  20. 'processors' => [
  21. ],
  22. ],
  23. ];

修改 config/autoload/exceptions.php

2.0 版本对 路由找不到(404)、请求方法不匹配(405) 等 HTTP 路由异常行为的处理逻辑进行了调整,统一改为抛出 Hyperf\HttpMessage\Exception\HttpException 的子异常类,然后通过 ExceptionHandler 来统一管理这些异常并做对应的响应处理,这样用户也可通过抛出对应的异常以获得一致的响应返回体验,但鉴于 ExceptionHandler 是一个由用户管理的机制,而在 1.1 版本下默认的 Skeleton 配置了一个 App\Exception\Handler\AppExceptionHandler 类来对异常进行托底处理,并统一以 500 状态码返回给客户端,故您需要将 2.0 版本提供的用来处理 HttpException 的 Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler 配置到 config/autoload/exceptions.php 配置文件中,并确保位于 App\Exception\Handler\AppExceptionHandler 配置的前面,以下配置示例省略了无关的配置,如下所示:

  1. <?php
  2. return [
  3. 'handler' => [
  4. 'http' => [
  5. Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler::class,
  6. ],
  7. ],
  8. ];

当您完成了 ExceptionHandler 的配置后,可以通过直接访问一个不存在的路由,如果响应的状态码为 404 即可理解为完成了此项配置的修改。

调整 composer.json 的依赖版本

由于要升级到 2.0 版本的组件,而原来 skeleton 项目默认情况下是依赖 1.1.x 版本的组件的,所以我们需要对依赖的约束条件进行一些调整,将原来所有 Hyperf 组件的依赖 ~1.1.0 修改为 ~2.0.0,修改完后需运行 composer update 来将依赖项升级到 2.0 版本。

完成升级

至此,2.0 版本发升级即已完成,但由于 Hyperf 的各个底层文件都是可以通过 DI 来实现重写的,如您重写了某些本次升级调整到了的框架内部文件,您仍需再根据您的实际情况进行一定的调整。

如您在升级上或升级后遇到任何的问题,请前往 Github Issue 提交您的 issue,说明您遇到的问题,我们会尽快帮助您解决。