等了这么久,Yii3 终于正式发布。经过多年的开发和打磨,这个版本带来了不少值得关注的变化。
Yii 框架一直以高性能、灵活、面向实践著称,Yii3 延续了这些特点,但在架构上做了彻底的重构。
相比 Yii 1.1 和 Yii 2.0,Yii3 主要解决了这些痛点:
下面整理一下这个版本的主要特性。如果想直接上手,可以看官方的入门指南。
Yii 1.1 和 Yii 2.0 都是单体框架,Yii3 则拆成了 130 多个独立包。这些包既可以单独使用,也可以通过应用模板组合成完整框架。想用哪个包就装哪个,不需要的不用背着。
官方提供了三种起步模板:
和 Yii 2.0 不同,这些模板很精简。路由、配置、DI 容器这些基础设施已经配好,但数据库之类的功能默认不装。需要什么自己加,不会有用不到的东西占空间。
Yii 2.0 主要用 Yii 自己的扩展,Yii3 则可以直接用 Packagist 上的任何包——PSR 标准包、Symfony 组件、通用 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 容器配置(接口到类的映射)和参数(用来配置这些类)。
'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 的传统,每个包在设计时都考虑了安全性。
主要功能:
还有 CSRF 保护之类的常用安全工具包。
文档里有专门的安全指南,包括安全响应流程。
Yii 2.0 的数据库抽象层本来就不错,Yii3 把它独立出来重新打磨了一遍。yiisoft/db 提供数据库访问、模式管理和查询构建器。迁移、数据库缓存这些工具也都基于它构建。Active Record 也有,实现更明确,性能依然很快。
$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 实现。
官方提供了这些后端:
框架大量使用 PSR 接口:
这种标准化设计保证了代码的可移植性,也能用上整个 PHP 生态的工具。
传统 PHP 服务器每个请求都要初始化框架和数据库连接,性能损耗不小。Yii3 支持和 RoadRunner、Swoole、FrankenPHP 配合跑 worker 模式。初始化一次,然后处理多个请求,响应时间能大幅降低。
不过 worker 模式下状态是共享的,要注意状态隔离和内存泄漏问题。Yii3 的包在设计时考虑了这点,要么不用状态,要么每次请求开始时会正确重置。
不是所有项目都要做前后端分离,传统服务端渲染的东西都有:小部件、视图(支持 Twig 等模板引擎)、表单、资源管理、HTML 辅助工具。
还提供了 Bootstrap 5 和 Bulma 的现成小部件。
构建 API 的工具也不少:
目前这些工具已经够用,后续还会继续扩充。
HTTP 层比之前版本更精确,遵循 PSR 接口。在底层接口之上有一些方便的抽象:
还有网络工具用来处理 IP 协议。
验证器基于 PHP 属性实现,可以从 HTTP 或其他地方填充表单数据。
<?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 = '';
}提供了一些常用的辅助工具:
国际化支持比较完善:
依赖倒置做得不错,单元测试比较容易写。基于 PSR 的请求响应抽象,API 测试不需要真的跑 HTTP 服务器。
yiisoft/test-support 提供了一些测试专用的 PSR 实现。
错误处理做得很细致。错误消息有上下文,不会只给你一个"Error"。开发模式下有"友好异常",会解释为什么出错、怎么修。据说后续还会加自动修复按钮。
错误页面会显示每层堆栈的源代码,出错的行会高亮。框架包的堆栈默认折叠,因为框架本身测试覆盖率很高,问题一般不在那。
yiisoft/error-handler 比 Yii2 的更强,能处理内存不足和致命错误,可以映射异常类型,支持不同格式响应。
还有 Sentry 集成包用来收集错误。
文档资源比较齐全:
代码质量标准很高。所有包都有接近 100% 的测试覆盖率、严格的 Psalm/PhpStan 类型检查,以及接近 100% 的变异测试分数。代码变更都要公开审查。
这些措施保证了框架的稳定性和可预测性。
遵循 SemVer。每个包独立版本控制。补丁版本只修 bug,次要版本加功能但保持兼容,主要版本才会引入破坏性变更。
还有一些不太显眼但很实用的功能:
框架功能很多,这里只是列了主要的。
一些有用的链接:
Yii3 经过多年开发终于发布,从单体框架转向包生态,解决了 Yii 2.0 的一些痛点。团队对代码质量要求很高,测试覆盖率和类型检查都做得很扎实。
官方的后续计划包括完善文档、发布更多工具包(队列、调试面板、Gii 等已经在打磨中)、收集反馈持续改进。
如果你在用 Yii 2.0 或者在选型 PHP 框架,可以关注一下 Yii3。