Yii3 正式发布了

等了这么久,Yii3 终于正式发布。经过多年的开发和打磨,这个版本带来了不少值得关注的变化。

Yii 框架一直以高性能、灵活、面向实践著称,Yii3 延续了这些特点,但在架构上做了彻底的重构。

相比 Yii 1.1 和 Yii 2.0,Yii3 主要解决了这些痛点:

  • Yii 2.0 生态封闭,接入通用 PHP 包比较麻烦
  • 一些魔术方法和隐式行为,对象的行为方式不太符合标准 PHP 习惯
  • 受限于向后兼容,对 PHP 新标准和现代特性的支持不够彻底
  • 内置的服务定位器等反模式,长期来看影响项目的可测试性和可维护性

下面整理一下这个版本的主要特性。如果想直接上手,可以看官方的入门指南。

从单体到包生态

Yii 1.1 和 Yii 2.0 都是单体框架,Yii3 则拆成了 130 多个独立包。这些包既可以单独使用,也可以通过应用模板组合成完整框架。想用哪个包就装哪个,不需要的不用背着。

三种应用模板

官方提供了三种起步模板:

  • Web — 服务端渲染应用
  • API — API 项目
  • Console — 命令行工具和后台 worker

和 Yii 2.0 不同,这些模板很精简。路由、配置、DI 容器这些基础设施已经配好,但数据库之类的功能默认不装。需要什么自己加,不会有用不到的东西占空间。

兼容整个 PHP 生态

Yii 2.0 主要用 Yii 自己的扩展,Yii3 则可以直接用 Packagist 上的任何包——PSR 标准包、Symfony 组件、通用 PHP 库都能接入,DI 容器会帮你配置好。

不再局限于框架自己的生态,也没有供应商锁定。想用什么库就用什么库,标准 PHP 接口保证了兼容性。

DI 容器是核心

整个框架围绕依赖注入容器构建。容器负责把各个包串起来,自动解析依赖。用法很直接:

php
return [
   // 接口到类的映射
   EngineInterface::class => EngineMarkOne::class,
   
   // 详细配置
   MyServiceInterface::class => [
       'class' => MyService::class,
       '__construct()' => [42],
       'setDiscount()' => [10],
   ],

   // 工厂闭包
   'api' => static fn(ApiConfig $config) => new ApiClient($config),
];

// 依赖根据类型提示自动注入
final readonly class MyController
{
   public function __construct(
       private CacheInterface $cache
   ) {}
}

容器在运行时工作,速度很快。配置就是实际执行的代码,没有魔术,需要的话可以直接用 XDebug 调试配置过程。

配置系统

配置方式延续了 Yii 2.0 的思路,支持多环境、配置覆盖等。默认按 web/API 和 console 分开,再加上共享配置。配置分两部分:DI 容器配置(接口到类的映射)和参数(用来配置这些类)。

php
'yiisoft/view' => [
    'basePath' => null,
    'parameters' => [
        'assetManager' => Reference::to(AssetManager::class),
        'applicationParams' => Reference::to(ApplicationParams::class),
        'aliases' => Reference::to(Aliases::class),
        'urlGenerator' => Reference::to(UrlGeneratorInterface::class),
        'currentRoute' => Reference::to(CurrentRoute::class),
    ],
],

'yiisoft/yii-view-renderer' => [
    'viewPath' => null,
    'layout' => '@src/Web/Shared/Layout/Main/layout.php',
    'injections' => [
        Reference::to(CsrfViewInjection::class),
    ],
],

安全特性

安全方面延续了 Yii 的传统,每个包在设计时都考虑了安全性。

主要功能:

  • 访问控制抽象
  • 用于访问控制的 RBAC 实现
  • JWT 认证
  • 应用的用户抽象
  • 用于处理代理链和头部的中间件
  • 第三方认证客户端

还有 CSRF 保护之类的常用安全工具包。

文档里有专门的安全指南,包括安全响应流程。

数据库层

Yii 2.0 的数据库抽象层本来就不错,Yii3 把它独立出来重新打磨了一遍。yiisoft/db 提供数据库访问、模式管理和查询构建器。迁移、数据库缓存这些工具也都基于它构建。Active Record 也有,实现更明确,性能依然很快。

php
$posts = $connection
   ->select(['id', 'title', 'created_at'])
   ->from('{{%posts}}')
   ->where(['status' => 'published'])
   ->andWhere(['>', 'views', 1000])
   ->orderBy(['created_at' => SORT_DESC])
   ->limit(10)
   ->all();

当然也可以用 Cycle ORM、Doctrine,或者直接用 PDO 和原生驱动。框架不强制你用哪种方案。

数据抽象

yiisoft/data 提供了数据抽象层,配合网格视图这些小部件,很适合做管理后台。支持数据格式化、分页、排序,数据源和展示层可以任意组合。

缓存

缓存比 Yii 2.0 更完善。内置缓存雪崩保护,驱动兼容 PSR-16,可以直接用任何 PSR-16 实现。

官方提供了这些后端:

  • APCu
  • DB
  • Files
  • Memcached
  • Redis

标准优先

框架大量使用 PSR 接口:

  • 日志 — 可以用 Yii 自己的日志,也可以换成 Monolog
  • 中间件 — Packagist 上的中间件包可以直接用,比如 CORS 处理
  • 请求-响应 — 基于 PSR,方便测试和 worker 模式
  • DI 容器 — 可以替换或组合其他 PSR 容器

这种标准化设计保证了代码的可移植性,也能用上整个 PHP 生态的工具。

Worker 模式

传统 PHP 服务器每个请求都要初始化框架和数据库连接,性能损耗不小。Yii3 支持和 RoadRunner、Swoole、FrankenPHP 配合跑 worker 模式。初始化一次,然后处理多个请求,响应时间能大幅降低。

不过 worker 模式下状态是共享的,要注意状态隔离和内存泄漏问题。Yii3 的包在设计时考虑了这点,要么不用状态,要么每次请求开始时会正确重置。

传统 Web 应用

不是所有项目都要做前后端分离,传统服务端渲染的东西都有:小部件、视图(支持 Twig 等模板引擎)、表单、资源管理、HTML 辅助工具。

还提供了 Bootstrap 5 和 Bulma 的现成小部件。

API 工具

构建 API 的工具也不少:

  • 数据响应处理
  • Swagger 支持

目前这些工具已经够用,后续还会继续扩充。

HTTP 和网络

HTTP 层比之前版本更精确,遵循 PSR 接口。在底层接口之上有一些方便的抽象:

  • HTTP 辅助工具(响应代码等)
  • Cookies
  • 文件下载响应工厂

还有网络工具用来处理 IP 协议。

输入验证

验证器基于 PHP 属性实现,可以从 HTTP 或其他地方填充表单数据。

php
<?php

declare(strict_types=1);

namespace App\Web\Echo;

use Yiisoft\FormModel\FormModel;
use Yiisoft\Validator\Label;
use Yiisoft\Validator\Rule\Length;

final class Form extends FormModel
{
    #[Label('The message to be echoed')]
    #[Length(min: 2)]
    public string $message = '';
}

辅助工具

提供了一些常用的辅助工具:

  • Arrays
  • Files
  • JSON
  • Strings
  • VarDumper

国际化

国际化支持比较完善:

  • 消息翻译(基于 intl 的 ICU 格式化)
  • 视图层支持
  • 路由器支持

测试

依赖倒置做得不错,单元测试比较容易写。基于 PSR 的请求响应抽象,API 测试不需要真的跑 HTTP 服务器。

yiisoft/test-support 提供了一些测试专用的 PSR 实现。

错误处理

错误处理做得很细致。错误消息有上下文,不会只给你一个"Error"。开发模式下有"友好异常",会解释为什么出错、怎么修。据说后续还会加自动修复按钮。

错误页面会显示每层堆栈的源代码,出错的行会高亮。框架包的堆栈默认折叠,因为框架本身测试覆盖率很高,问题一般不在那。

yiisoft/error-handler 比 Yii2 的更强,能处理内存不足和致命错误,可以映射异常类型,支持不同格式响应。

还有 Sentry 集成包用来收集错误。

文档

文档资源比较齐全:

  • 权威指南 — 框架整体使用文档
  • 社区食谱 — 实战案例
  • API 文档 — 所有包的公共 API
  • 包文档 — 每个包的独立文档

代码质量

代码质量标准很高。所有包都有接近 100% 的测试覆盖率、严格的 Psalm/PhpStan 类型检查,以及接近 100% 的变异测试分数。代码变更都要公开审查。

这些措施保证了框架的稳定性和可预测性。

发布策略

遵循 SemVer。每个包独立版本控制。补丁版本只修 bug,次要版本加功能但保持兼容,主要版本才会引入破坏性变更。

其他特性

还有一些不太显眼但很实用的功能:

  • 别名
  • 事件
  • 分析器
  • 需求检查器
  • 邮件发送器
  • 控制台
  • 互斥锁(支持多种后端)

框架功能很多,这里只是列了主要的。

相关资源

一些有用的链接:

  • 官方登陆页面
  • 入门指南
  • API 文档
  • Yii3 包仓库
  • Telegram 群组
  • Yii 项目网站
  • Facebook 群组
  • X (Twitter) 动态
  • LinkedIn 群组

写在最后

Yii3 经过多年开发终于发布,从单体框架转向包生态,解决了 Yii 2.0 的一些痛点。团队对代码质量要求很高,测试覆盖率和类型检查都做得很扎实。

官方的后续计划包括完善文档、发布更多工具包(队列、调试面板、Gii 等已经在打磨中)、收集反馈持续改进。

如果你在用 Yii 2.0 或者在选型 PHP 框架,可以关注一下 Yii3。

本作品采用《CC 协议》,转载必须注明作者和本文链接