# 版本 4.6.0

发布日期：2025 年 1 月 19 日

CodeIgniter4 的 4.6.0 版本发布

## 重大变更

### 行为变更

#### 异常处理

异常类已重新设计。详细信息请参阅 异常设计。 以下是相应的破坏性变更：

- `Validation::setRule()` 现在抛出 `CodeIgniter\Exceptions\InvalidArgumentException` 而非 `TypeError`

- `CriticalError` 现在继承自 `CodeIgniter\Exceptions\RuntimeException` 而非 `Error`

- `DatabaseException` 现在继承自 `CodeIgniter\Exceptions\RuntimeException` 而非 `Error`

- `ConfigException` 现在继承自 `CodeIgniter\Exceptions\RuntimeException` 而非 `CodeIgniter\Exceptions\CriticalError`

- `TestException` 现在继承自 `CodeIgniter\Exceptions\LogicException` 而非 `CodeIgniter\Exceptions\CriticalError`

#### 过滤器变更

`Filters` 类已修改，允许在 before 或 after 阶段使用不同参数多次运行相同过滤器。详细信息请参阅 Upgrading Guide。

#### 注册器

新增检查以防止注册器自动发现机制重复运行。若重复执行将抛出异常。详细信息请参阅 注册器的脏数据修复。

#### Time::createFromTimestamp()

`Time::createFromTimestamp()` 处理时区的方式已变更。若未显式传递 `$timezone` 参数，实例时区将设为 UTC（此前使用系统默认时区）。详细信息请参阅 Upgrading Guide。

#### 支持微秒的时间处理

修复了 `Time` 类中部分方法丢失微秒的缺陷。详细信息请参阅 Upgrade Guide。

#### Time::setTimestamp()

`Time::setTimestamp()` 的行为已修正。详细信息请参阅 Upgrade Guide。

#### 非 HTML 请求的错误报告

旧版本中，当请求不接受 HTML 时，CodeIgniter 仅在 `development` 和 `testing` 环境下显示错误详情。

由于在自定义环境中无法显示错误详情，现修正此行为：只要 PHP 配置中的 `display_errors` 启用即显示错误详情。

此修正后，HTML 请求与非 HTML 请求的错误详情显示条件现已统一。

#### 会话 ID (SID)

现在 `Session` 类库强制使用 PHP 默认的 32 字符 SID（每字符 4 位熵值）。详细信息请参阅 Upgrade Guide。

#### 响应头处理

通过 `Response` 类设置的响应头将覆盖通过 PHP `header()` 函数设置的响应头。

旧版本中，`Response` 类设置的响应头会追加到现有响应头（无法修改），当存在互斥指令的同名响应头时可能导致意外行为。

例如，session 会自动通过 `header()` 函数设置响应头：

    Expires: Thu, 19 Nov 1981 08:52:00 GMT
    Cache-Control: no-store, no-cache, must-revalidate
    Pragma: no-cache

若再次设置 Expires 响应头将导致重复：

    $response->removeHeader('Expires'); // 无效操作
    return $response->setHeader('Expires', 'Sun, 17 Nov 2024 14:17:37 GMT');

响应头结果：

    Expires: Thu, 19 Nov 1981 08:52:00 GMT
    // ...
    Expires: Sun, 17 Nov 2024 14:17:37 GMT

此时浏览器可能无法正确识别有效响应头。本版本变更后，旧响应头将被覆盖：

    Cache-Control: no-store, no-cache, must-revalidate
    Pragma: no-cache
    Expires: Sun, 17 Nov 2024 14:17:37 GMT

### 接口变更

备注

只要你未扩展相关 CodeIgniter 核心类或实现这些接口，所有变更均向后兼容且无需调整。

- Router: 以下方法已加入 `RouteCollectionInterface` 接口：

  > - `getDefaultNamespace()`

  > - `getRoutesOptions()`

  > - `setHTTPVerb()`

  > - `isFiltered()`

  > - `getFiltersForRoute()`

### 方法签名变更

- Router: `DefinedRouteCollector` 的构造函数参数类型由 `RouteCollection` 改为 `RouteCollectionInterface`

- View: `renderSection()` 方法的返回类型改为 `string`，且不再调用 `echo`

- Time: `createFromTimestamp()` 的首个参数类型由 `int` 改为 `int|float`，并新增返回类型 `static`

- Helpers: 更新了 `character_limiter()` 的参数命名。若使用命名参数需更新函数调用

#### 移除类型定义

- Database:

    - 移除 `BaseConnection::escapeIdentifier()` 首个参数的 `string` 类型

    - 移除 `BaseConnection::getFieldNames()` 和 `SQLite3\Connection::getFieldNames()` 首个参数的 `string` 类型

    - 移除 `BaseConnection::_listColumns()`、`MySQLi\Connection::_listColumns()`、`OCI8\Connection::_listColumns()`、`Postgre\Connection::_listColumns()`、`SQLSRV\Connection::_listColumns()`、`SQLite3\Connection::_listColumns()` 首个参数的 `string` 类型

### 移除已弃用项

- API: 移除 `CodeIgniter\API\ResponseTrait` 中已弃用的 `failValidationError()` 方法，改用 `failValidationErrors()`

- HTTP: 移除 `CodeIgniter\HTTP\Response` 和 `ResponseInterface` 中已弃用的 `getReason()` 方法，改用 `getReasonPhrase()`

- Logger: 移除已弃用的 `CodeIgniter\Log\Logger::cleanFilenames()` 和 `CodeIgniter\Test\TestLogger::cleanup()` 方法，改用 `clean_path()` 函数

- Router: 移除已弃用的 `CodeIgniter\Router\Exceptions\RedirectException` 异常类，改用 `CodeIgniter\HTTP\Exceptions\RedirectException`

- Constants: 移除已弃用的 `EVENT_PRIORITY_*` 常量，改用类常量 `CodeIgniter\Events\Events::PRIORITY_LOW`、`CodeIgniter\Events\Events::PRIORITY_NORMAL` 和 `CodeIgniter\Events\Events::PRIORITY_HIGH`

- View: 移除已弃用的 `CodeIgniter\View\View::$currentSection` 属性

- Config: 移除已弃用的 `Config\Cache::$storePath` 属性，改用 `Config\Cache::$file['storePath']`

- Formatter: 移除已弃用的 `Config\Format::getFormatter()` 方法，改用 `CodeIgniter\Format\Format::getFormatter()`

- Security: 移除 `Config\Security::$samesite` 配置项，改用 `Config\Cookie::$samesite`

- Cookie: 移除 `CodeIgniter\Cookie\CookieStore` 中的 `dispatch()`、`setRawCookie()`、`setCookie()` 方法，这些方法已移至 `CodeIgniter\HTTP\ResponseTrait`

## 功能增强

### 发布器

- `Publisher::discover()` 新增第二个参数（`namespace`）用于指定搜索发布器的命名空间。详细信息请参阅 在指定命名空间中发现。

### 异常处理

异常类已重新设计。详细信息请参阅 异常设计。 新增以下异常类：

- `CodeIgniter\Exceptions\LogicException`

- `CodeIgniter\Exceptions\RuntimeException`

- `CodeIgniter\Exceptions\BadFunctionCallException`

- `CodeIgniter\Exceptions\BadMethodCallException`

- `CodeIgniter\Exceptions\InvalidArgumentException`

新增以下异常接口：

- `CodeIgniter\Files\Exceptions\ExceptionInterface`

- `CodeIgniter\HTTP\Exceptions\ExceptionInterface`

- `CodeIgniter\Router\Exceptions\ExceptionInterface`

非 HTML 响应的异常显示现基于 PHP 的 `display_errors` 设置，而非硬编码环境判断。

### 命令行工具

- `spark routes` 和 `spark filter:check` 命令现显示过滤器参数

- `spark filter:check` 命令现显示过滤器类名

- 新增 `spark lang:sync` 命令用于同步翻译文件。详细信息请参阅 通过命令同步翻译文件

- `spark phpini:check` 命令新增可选 `opcache` 参数，用于显示 opcache 设置信息

### 路由

- 现可在限制路由时指定多个主机名

### 协商器

- 新增 `Feature::$strictLocaleNegotiation` 特性开关，用于启用严格的语言环境匹配。 此前，若请求头包含 `Accept-language: en-US,en-GB;q=0.9`，系统可能会返回首个匹配的语言（如 `en`），而非精确匹配 `en-US` 或 `en-GB`。 将此值设为 `true` 后，匹配逻辑将不再仅基于语言代码（'en' - ISO 639-1），还会校验地区代码（'en-US' - ISO 639-1 及 ISO 3166-1 alpha）。

### 分页

- 新增获取当前页总条目数和范围的功能。 详细信息请参阅 显示条目数。

### 数据库

#### 其他改进

- 为 MySQLi 新增 `foundRows` 配置项以使用 `MYSQLI_CLIENT_FOUND_ROWS`

- 新增 `BaseConnection::resetTransStatus()` 方法用于重置事务状态。详细信息请参阅 重置事务状态

- SQLite3 新增 `synchronous` 配置项，用于调整事务期间磁盘刷写策略。结合 `WAL` 日志模式时可有效优化性能

### 类库

- File: `File` 类新增 `getSizeByBinaryUnit()` 和 `getSizeByMetricUnit()` 方法。 详细信息请参阅 File::getSizeByBinaryUnit() 和 File::getSizeByMetricUnit()。

- FileCollection: `FileCollection` 类新增 `retainMultiplePatterns()` 方法。 详细信息请参阅 FileCollection::retainMultiplePatterns()。

- Validation: `FileRules` 类新增 `min_dims` 验证规则。 详细信息请参阅 Validation。

- Validation: `is_unique` 和 `is_not_unique` 规则现允许在首个参数中指定 `dbGroup`。 详细信息请参阅 Validation。

### 其他

- Filters: 现可在 before 或 after 阶段使用不同参数多次执行同一过滤器

- Services: 新增 `BaseService::resetServicesCache()` 方法用于重置服务缓存。 详细信息请参阅 重置服务缓存

- Errors: 新增默认的 "400 Bad Request" 错误页面

## 消息变更

- 新增 `Validation.min_dims` 消息

- 新增 `Errors.badRequest` 和 `Errors.sorryBadRequest` 消息

## 变更列表

### 异常处理

异常类已重新设计。详细信息请参阅 异常设计。 以下是相应变更：

- 缓存处理器类的 `deleteMatching()` 方法现抛出 `CodeIgniter\Exceptions\BadMethodCallException` 而非 `Exception`

- `Cache\ResponseCache::get()` 现抛出 `CodeIgniter\Exceptions\RuntimeException` 而非 `Exception`

- 原抛出 `RuntimeException` 的类现改为抛出 `CodeIgniter\Exceptions\RuntimeException`

- 原抛出 `InvalidArgumentException` 的类现改为抛出 `CodeIgniter\Exceptions\InvalidArgumentException`

- 原抛出 `LogicException` 的类现改为抛出 `CodeIgniter\Exceptions\LogicException`

- 原抛出 `BadMethodCallException` 的类现改为抛出 `CodeIgniter\Exceptions\BadMethodCallException`

- 原抛出 `BadFunctionCallException` 的类现改为抛出 `CodeIgniter\Exceptions\BadFunctionCallException`

- `RedirectException` 现继承自 `CodeIgniter\Exceptions\RuntimeException` 而非 `Exception`

- `PageNotFoundException` 现继承自 `CodeIgniter\Exceptions\RuntimeException` 而非 `OutOfBoundsException`

## 已弃用项

- Filters:

    - 弃用 `Filters` 的 `$arguments` 和 `$argumentsClass` 属性（不再使用）

    - 弃用 `Filters::getArguments()` 方法（不再使用）

- File:

    - 弃用 `File` 的 `getSizeByUnit()` 方法，改用 `getSizeByBinaryUnit()` 或 `getSizeByMetricUnit()`

## Bug 修复

- Response:

    - 现在通过 `Response` 类设置的响应头将优先覆盖通过 PHP `header()` 函数手动设置的响应头

- View: 为 `View::excerpt()` 新增多字节字符串支持

- Helpers: 为 `excerpt()` 新增多字节字符串支持

请查看仓库的 CHANGELOG.md 以获取完整的 Bug 修复列表。