# 3.1 升级指南

- 3.1 版本主要修改了 `PHP` 最低版本为 `8.1`，`Swoole` 最低版本为 `5.0`
- 引入 `Pest` 测试框架
- 新增 `hyperf/helper`，`Hyperf\Utils` 中原有 `不包含命名空间助手函数` 迁移至 `hyperf/helper` 中
- 改变 `hyperf/config` 多层级配置文件的加载方式，支持 `.` 语法，如 `config('a.c')`

## Utils 包变动

原有 utils 包中的助手函数没有添加命名空间，可能与其他 composer 包的函数冲突，在 3.1 中进行了移除替换。

对此有两种方式进行处理：

1. 确定程序中没有加载会导致函数冲突的包，可以选择直接安装 `hyperf/helper` 即可，`helper` 包中提供不包含命名空间的助手函数，与原有 `utils` 中一致
2. 在原有调用助手函数的地方增加命名空间，可以使用 `rector` 进行重构，参考[重构文档](https://github.com/orgs/hyperf/discussions/5635)

## 配置文件加载方式变动

在 3.0 中，配置是以 `配置文件名` 作为键值存在， 而在 3.1 中，`hyperf/config` 多层级配置文件的加载方式，是以 `相对目录.配置文件名` 作为键值存在。

支持 `.` 语法，如 `config('a.c')`。

对此需要注意原有项目中以下两种情况的处理

- 3.0 项目中在 `config/autoload` 中创建了子目录，如 `config/autoload/sub/a.php` ，原有的 `config('a')` 需要修改为 `config('sub.a')`。
- 3.0 项目中的配置文件名中包含`.`，如 `config/autoload/a.b.php` ，会在使用 `config('a')` 的时候返回以下结构，如果你同时还存在 `config/autoload/a.php` 配置文件，还将得到合并配置项后的结果。

```php
return [
    'a.php中的配置项' => 'a.php中的配置值',
    'b' => [
        'a.b.php中的配置项' => 'a.b.php中的配置值',
    ]
];
```

## 其他改动

1. 从 v3.1 版本开始，`hyperf/metirc` 组件不再默认安装 `prometheus` 依赖，所以需要使用 `prometheus` 引擎的开发者，需要执行以下命令加载依赖：

```bash
composer require promphp/prometheus_client_php
```

2. `Request` 和 `Response` 的 `withHeaders` 功能发生变化

v3.1 之前的版本会对原来的数据进行保存，类似于 `array_merge` 原数据，v3.1 版本之后，则是直接将所有的 `headers` 进行替换

```php
<?php
// v3.1 之前
$request->withHeader('foo', 1)->withHeader('bar', 2); // ['foo' => [1], 'bar' => [2]]
$request->withHeader('foo', 1)->withHeader('foo', 2); // ['foo' => [2]]
$request->withAddedHeader('foo', 1)->withAddedHeader('foo', 2); // ['foo' => [1, 2]]

$request->withHeaders(['foo' => 1])->withHeaders(['bar' => 2]); // ['foo' => [1], 'bar' => [2]]

// v3.1 之后
$request->withHeader('foo', 1)->withHeader('bar', 2); // ['foo' => [1], 'bar' => [2]]
$request->withHeader('foo', 1)->withHeader('foo', 2); // ['foo' => [2]]
$request->withAddedHeader('foo', 1)->withAddedHeader('foo', 2); // ['foo' => [1, 2]]

$request->withHeaders(['foo' => 1])->withHeaders(['bar' => 2]); // ['bar' => [2]]

$request->setHeader('foo', 1)->setHeader('bar', 2); // ['foo' => [1], 'bar' => [2]]
$request->setHeader('foo', 1)->setHeader('foo', 2); // ['foo' => [2]]
$request->addHeader('foo', 1)->addHeader('foo', 2); // ['foo' => [1, 2]]

$request->setHeaders(['foo' => 1])->setHeaders(['bar' => 2]); // ['bar' => [2]]

```
3. `AMQP` 消费者 `consumeMessage` 方法返回值调整为 `Result` 枚举

```php
<?php
// v3.1之前
public function consumeMessage($data, AMQPMessage $message): string
{
    return Result::ACK;
}
// v3.1之后
public function consumeMessage($data, AMQPMessage $message): Result
{
    return Result::ACK;
}
```
