docs/en/upgrade/2.0.md
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.
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 .
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);
composer.jsonDue 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"
}
}
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.
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.
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.
config/autoload/logger.phpBecause 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' => [
],
],
];
config/autoload/exceptions.phpVersion 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.
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 -> _simpleRequestclientStreamRequest -> _clientStreamRequestgetGrpcClient -> _getGrpcClientIn 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.
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;
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),
];
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.
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.
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,
],
],
]
];
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.
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.