hyperf/docs/zh-tw/upgrade/2.0.md
2020-06-22 17:09:53 +08:00

9.8 KiB
Raw Blame History

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();,如下所示:

<?php

ini_set('display_errors', 'on');
ini_set('display_startup_errors', 'on');

error_reporting(E_ALL);
date_default_timezone_set('Asia/Shanghai');

! defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 1));
! defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL);

require BASE_PATH . '/vendor/autoload.php';

// Self-called anonymous function that creates its own scope and keep the global namespace clean.
(function () {
    Hyperf\Di\ClassLoader::init();

    /** @var \Psr\Container\ContainerInterface $container */
    $container = require BASE_PATH . '/config/container.php';

    $application = $container->get(\Hyperf\Contract\ApplicationInterface::class);
    $application->run();
})();

與此同時PHPUnit 的入口檔案也許做同樣的處理,檔案位於 tests/bootstrap.php,如下所示:

<?php

declare(strict_types=1);

error_reporting(E_ALL);
date_default_timezone_set('Asia/Shanghai');

! defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 1));
! defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL);

Swoole\Runtime::enableCoroutine(true);

require BASE_PATH . '/vendor/autoload.php';

Hyperf\Di\ClassLoader::init();

$container = require BASE_PATH . '/config/container.php';

$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 語句。

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

調整 composer.json 的依賴版本

由於要升級到 2.0 版本的元件,而原來 skeleton 專案預設情況下是依賴 1.1.x 版本的元件的,所以我們需要對依賴的約束條件進行一些調整,將原來所有 Hyperf 元件的依賴 ~1.1.0 修改為 ~2.0.0,同時您還需要將 phpstan/phpstan 版本依賴修改為 ^0.12,修改完後需執行 composer update 來將依賴項升級到 2.0 版本。

調整 Dockerfile

在 Docker 映象的打包過程中,主動執行 php bin/hyperf.php 命令會幫助提前建立所有需要生成的代理類和註解掃描快取,這樣在生產環境執行啟動時便無需再次的掃描,這樣可以極大的優化生產環境啟動的時間和記憶體使用量。以下示例不包含未修改的 Dockerfile 程式碼。

ENV TIMEZONE=${timezone:-"Asia/Shanghai"} \
    APP_ENV=prod \
    SCAN_CACHEABLE=(true)

COPY . /opt/www
RUN composer install --no-dev -o && php bin/hyperf.php

EXPOSE 9501

ENTRYPOINT ["php", "/opt/www/bin/hyperf.php", "start"]

Docker 部署的使用者,需要注意的是,在重新啟動服務之前,最好先執行一次 php bin/hyperf.php 後再重新啟動服務,以減少重新啟動時的耗時。

調整 config/config.php 配置檔案

您需要在 config/config.php 配置中新增 app_envscan_cacheable 兩個配置項,下面的程式碼示例不包含其它無關的配置內容,如下所示:

<?php

return [
    // 生產環境使用 prod 值
    'app_env' => env('APP_ENV', 'dev'),
    // 是否使用註解掃描快取
    'scan_cacheable' => env('SCAN_CACHEABLE', false),
];

scan_cacheable 配置用於控制應用啟動時是否使用註解掃描快取,以上 Dockerfileconfig/config.php 中都有相關的修改。當這個配置的值為 true 時,專案啟動時則會認為所有類都已經完成了掃描並正確生成了對應的快取和代理,則會跳過掃描階段以便優化啟動時間和減少記憶體開銷。

修改 config/autoload/logger.php

因為 2.0 版本提高了對 Monolog 依賴的版本,在高版本的 Monolog 中,預設的日誌格式發生了變化,如果對於日誌的格式有要求,比如需要根據日誌格式與日誌系統對接等,可修改 config/autoload/logger.php 配置檔案的 dateFormat 配置項,以保持與之前版本的一致。

<?php

declare(strict_types=1);

return [
    'default' => [
        'handler' => [
            'class' => Monolog\Handler\StreamHandler::class,
            'constructor' => [
                'stream' => BASE_PATH . '/runtime/logs/hyperf.log',
                'level' => Monolog\Logger::DEBUG,
            ],
        ],
        'formatter' => [
            'class' => Monolog\Formatter\LineFormatter::class,
            'constructor' => [
                'format' => null,
                'dateFormat' => 'Y-m-d H:i:s',
                'allowInlineLineBreaks' => true,
            ],
        ],
        'processors' => [
        ],
    ],
];

修改 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 配置的前面,以下配置示例省略了無關的配置,如下所示:

<?php
return [
    'handler' => [
        'http' => [
            Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler::class,
        ],
    ],
];

當您完成了 ExceptionHandler 的配置後,可以通過直接訪問一個不存在的路由,如果響應的狀態碼為 404 即可理解為完成了此項配置的修改。

修改 gRPC 客戶端

為了避免和 gRPC 實際業務的命名衝突2.0 版本對 gRPC 客戶端的基類函式命名進行了調整。

  • simpleRequest -> _simpleRequest
  • clientStreamRequest -> _clientStreamRequest
  • getGrpcClient -> _getGrpcClient

除此之外,一些不應該暴露的方法變成了私有方法,如您的 gRPC 客戶端涉及到以上方法的呼叫,請進行命名上的調整。

移除 DI 懶載入監聽器

如果您的專案中有使用到 DI 元件的懶載入功能,此前您需要註冊一個 Hyperf\Di\Listener\LazyLoaderBootApplicationListener 監聽器,而在 2.0 版本,這一監聽器被移除了,您可以直接使用該功能,故如果您此前有使用到該功能,您需要在 config/autoload/listeners.php 中移除該監聽器的註冊;

繫結 NormalizerInterface 關係

當您使用了 JSONRPC 功能並使用了 symfony/serializer 庫來提供序列化功能時,由於 2.0 版本不再自動對映 Hyperf\Contract\NormalizerInterface 的實現類,所以您需要手動新增該對映關係,如下:

use Hyperf\Utils\Serializer\SerializerFactory;
use Hyperf\Utils\Serializer\Serializer;

return [
    Hyperf\Contract\NormalizerInterface::class => new SerializerFactory(Serializer::class),
];

調整 Hyperf\Contract\ProcessInterface 的實現類

Hyperf\Contract\ProcessInterface 中的 isEnable 方法增加了一個 $server 引數,即 isEnable($server): bool,所有 ProcessInterface 的實現類都需要您對該方法進行一些調整。

完成升級

至此2.0 版本發升級即已完成,但由於 Hyperf 的各個底層檔案都是可以通過 DI 來實現重寫的,如您重寫了某些本次升級調整到了的框架內部檔案,您仍需再根據您的實際情況進行一定的調整。

如您在升級上或升級後遇到任何的問題,請前往 Github Issue 提交您的 issue說明您遇到的問題我們會盡快幫助您解決。