hyperf/docs/en/upgrade/2.0.md
2022-10-31 00:47:12 +07:00

13 KiB

2.0 Upgrade Guide

Version 2.0 has added many powerful functions. If you have already invested in a project for business use and created an application project of version 1.1 based on the officially provided Skeleton project, you can adjust your Skeleton project according to the following points: If you are a new project, follow the documentation to create a new project through the composer create-project hyperf/hyperf-skeleton command to use the new 2.0 version of the skeleton code, if you are currently using a version lower than 1.1 , then you need to upgrade to 1.1 first and then upgrade to 2.0 according to this upgrade guide.

Upgrade Swoole to 4.5+

Version 2.0 has raised the minimum Swoole version requirement from 4.4+ to 4.5+. There are some differences in usage details between the two versions. Hyperf has adapted to this version difference in earlier versions, so you can ignore it. The difference details, upgrading the Swoole version to 4.5+ is mainly to reduce the long-term impact of the historical baggage on Hyperf. You can check the Swoole version in the current environment by executing php --ri swoole. You can complete the upgrade of Swoole according to the Swoole documentation .

Entry file adds ClassLoader initialization

2.0 has changed the underlying logic of AOP, so you need to add a line of initialization code in the framework entry file bin/hyperf.php, you need to add the code Hyperf\Di\ClassLoader:: in the first line of the entry anonymous function init();, as follows:

<?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();
})();

Meanwhile, the PHPUnit entry file might do the same, located in tests/bootstrap.php, like this:

<?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);

Adjust composer.json

Due to the adjustment of the underlying logic of AOP in version 2.0, the init-proxy.sh script has been removed, so you need to remove the "init-proxy' in scripts.post-autoload-dumpfromcomposer.json. sh" to execute the statement, and modify the command in post-autoload-dump to the rm -rf runtime/container statement.

{
    "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"
    }
}

Adjust the dependency version of composer.json

Since we want to upgrade to the 2.0 version of the component, and the original skeleton project relies on the 1.1.x version of the component by default, we need to make some adjustments to the constraints of the dependency, and change the dependencies of all the original Hyperf components to ~1.1.0 is modified to ~2.0.0, and you also need to modify the phpstan/phpstan version dependency to ^0.12, after the modification, you need to run composer update to upgrade the dependencies to version 2.0.

Adjust Dockerfile

During the packaging process of the Docker image, actively executing the php bin/hyperf.php command will help to create all the proxy classes and annotation scanning caches that need to be generated in advance, so that there is no need to scan again when the production environment is started, which can be extremely Greatly optimized production startup time and memory usage. The following examples do not contain unmodified Dockerfile code.

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"]

For users who are not deployed by Docker, it should be noted that before restarting the service, it is best to execute php bin/hyperf.php and then restart the service to reduce the time-consuming restart.

Adjust the config/config.php configuration file

You need to add two configuration items app_env and scan_cacheable to the config/config.php configuration. The following code example does not contain other irrelevant configuration content, as shown below:

<?php

return [
    // The production environment uses the prod value
    'app_env' => env('APP_ENV', 'dev'),
    // Whether to scan the cache with annotations
    'scan_cacheable' => env('SCAN_CACHEABLE', false),
];

The scan_cacheable configuration is used to control whether to use annotations to scan the cache when the application starts. There are related modifications in the above Dockerfile and config/config.php. When the value of this configuration is true, when the project starts, it will consider that all classes have been scanned and the corresponding caches and proxies have been correctly generated, and the scanning phase will be skipped to optimize startup time and reduce memory overhead.

Modify config/autoload/logger.php

Because version 2.0 has improved the version that depends on Monolog, in the higher version of Monolog, the default log format has changed. If there are requirements for the log format, such as the need to connect with the log system according to the log format, you can modify config/ The dateFormat configuration item of the autoload/logger.php configuration file to keep it consistent with the previous version.

<?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' => [
        ],
    ],
];

Modify config/autoload/exceptions.php

Version 2.0 adjusted the processing logic of HTTP routing exception behaviors such as route not found (404), request method mismatch (405), etc., and changed to throw a sub-exception class of Hyperf\HttpMessage\Exception\HttpException, and then ExceptionHandler is used to uniformly manage these exceptions and handle corresponding responses, so that users can also get a consistent response return experience by throwing corresponding exceptions, but since ExceptionHandler is a user-managed mechanism, the default in version 1.1 Skeleton configures an App\Exception\Handler\AppExceptionHandler class to handle the exception and return it to the client with a 500 status code, so you need to use the Hyperf\HttpServer provided by version 2.0 to handle HttpException \Exception\Handler\HttpExceptionHandler is configured in the config/autoload/exceptions.php configuration file, and make sure to be in front of the App\Exception\Handler\AppExceptionHandler configuration, the following configuration example omits extraneous configuration, as shown below :

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

After you complete the configuration of ExceptionHandler, you can directly access a route that does not exist. If the response status code is 404, it can be understood that the modification of this configuration is completed.

Modify the gRPC client

In order to avoid naming conflicts with the actual business of gRPC, version 2.0 has adjusted the naming of the base class functions of the gRPC client.

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

In addition, some methods that should not be exposed have become private methods. If your gRPC client involves the invocation of the above methods, please adjust the naming.

Remove DI lazy load listener

If your project uses the lazy loading function of DI components, you need to register a Hyperf\Di\Listener\LazyLoaderBootApplicationListener listener, but in version 2.0, this listener has been removed, you can use it directly This function, so if you have used this function before, you need to remove the registration of the listener in config/autoload/listeners.php;

Bind the NormalizerInterface relationship

When you use the JSONRPC function and use the symfony/serializer library to provide serialization functions, since version 2.0 no longer automatically maps the implementation class of Hyperf\Contract\NormalizerInterface, you need to manually add the mapping relationship, as follows :

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

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

Adjust the implementation class of Hyperf\Contract\ProcessInterface

The isEnable method in Hyperf\Contract\ProcessInterface adds a $server parameter, isEnable($server): bool, all implementation classes of ProcessInterface require you to make some adjustments to this method.

Check the config/autoload/aspects.php file

If you have done some thinning operations on Skeleton before, you need to check whether the config/autoload/aspects.php file exists, if not, you need to add a file and return an empty array.

This problem will be fixed in 2.0.1, so this check is not required in the future.

Check the collector for custom annotations

If you use custom annotations and use a custom collector Collector to collect annotation metadata, you need to configure the corresponding Collector in annotations.scan.collectors, because in development mode, it will be based on the file The modification time determines whether the file is modified, and then decides whether to re-collect the corresponding annotation metadata. So, when annotations.scan.collectors is not configured, it will cause the annotations to take effect only when the server is started for the first time.

As in the application layer, the configuration is located in the config/autoload/annotations.php file, as follows:

<?php

return [
    'scan' => [
        'collectors' => [
            CustomCollector::class,
        ],
    ],
];

For components, the configuration is provided by ConfigProvider, as follows:

<?php

return [
    'annotations' => [
        'scan' => [
            'collectors' => [
                CustomCollector::class,
            ],
        ],
    ]
];

Start the service and test the access interface

When using Swoole 4.5 and the view component, if there is a problem with interface 404, you can try to delete the static_handler_locations configuration item in the config/autoload/server.php file.

Paths under this configuration will be considered static file routes, so if / is configured, it will cause all interfaces to be considered file paths, resulting in interface 404.

complete the upgrade

At this point, the upgrade of version 2.0 has been completed, but since each underlying file of Hyperf can be rewritten through DI, if you rewrite some internal files of the framework adjusted in this upgrade, you still need to rewrite it according to your to make some adjustments to the actual situation.

If you encounter any problems during or after the upgrade, please go to Github Issue to submit your issue, explain the problem you have encountered, and we will try to fix it as soon as possible help you out.