从 Yii 1.1 升级到 Yii 2.0:核心差异全解析与迁移实战指南

原创2026-09-21 09:19:42405 阅读
文章标签:后端Web框架

从 Yii 1.1 升级到 Yii 2.0:核心差异全解析与迁移实战指南

Yii 2.0 对框架进行了完全重写,从 1.1 升级并非简单的版本号跨越,而是一次架构与使用方式的全面重构。本文以 docs/guide-fr/intro-upgrade-from-v1.md 为骨架,结合当前仓库(yiisoft/yii2 源码镜像)中的真实实现,系统梳理两个大版本在 PHP 语言基础、类体系、MVC 分层、数据访问、安全与 URL 管理等维度的核心差异,帮助 Yii 1.1 开发者快速定位迁移要点,掌握 2.0 的新范式。读完本文,你将获得一份可直接对照源码逐项迁移的完整行动清单。

本文面向已有 Yii 1.1 使用经验的开发者。如果你是全新用户,可直接从 docs/guide-fr/start-installation.md 的安装指南开始。本文对应的英文原版见 docs/guide/intro-upgrade-from-v1.md,英文版在 URL 规则、行为基类等细节上略有补充,可对照阅读。

安装方式与 PHP 环境要求的根本变化

Composer 驱动的全新安装流程

Yii 2.0 全面拥抱 Composer 以及 framework/composer.json(包名 yiisoft/yii2)即为此机制的落地证据:框架本身就是一个可被 Composer 安装、可发布扩展的标准化包。

迁移时要特别注意两点:

PHP 版本门槛与语言特性红利

Yii 2.0 要求 PHP 5.4 及以上,相比 1.1 的 PHP 5.2 是一个巨大进步(注意:当前仓库代码已进一步演进,实际使用请以你部署环境为准,本文的 5.4 是原文档记载的 2.0 发布门槛)。随之而来的是语言层面的可用特性大幅增加,迁移代码时可以放心使用:

  • 命名空间(Namespaces):代码组织方式发生根本变化,见下文专节;
  • 匿名函数(Anonymous functions):事件回调、验证器、排序比较等场景大量使用;
  • 短数组语法:[...elements...] 取代 array(...elements...),这也是本文所有示例采用 [] 的原因;
  • 短 echo 标签:视图文件中可直接使用 <?=,从 PHP 5.4 起无需任何额外配置;
  • SPL 类与接口:ArrayAccess、IteratorAggregate、ReflectionClass 等被框架内部广泛依赖(例如 framework/base/Model.php 实现 IteratorAggregate、ArrayAccess、Arrayable 接口);
  • Late Static Bindings(延迟静态绑定):static:: 在 Active Record 查询、find() 返回子类实例等场景中发挥关键作用;
  • Date and Time:改进的日期时间 API;
  • Traits(特性):框架用它复用行为,如 framework/base/Model.php 中的 ArrayableTrait、StaticInstanceTrait;
  • intl 扩展:2.0 的国际化功能依赖 PHP 的 intl 扩展,这与下文 I18N 一节直接相关,部署环境需确保该扩展可用。

命名空间:类名与文件路径的统一

2.0 最直观的变化是全面采用命名空间。几乎每个核心类都带命名空间,例如 yii\web\Request;类名前的 “C” 前缀(如 CController、CComponent)被彻底移除。命名规则现在与目录结构一一对应:yii\web\Request 对应的类文件就是框架目录下的 web/Request.php(即 framework/web/Request.php),yii\db\ActiveQuery 对应 framework/db/ActiveQuery.php,yii\base\Model 对应 framework/base/Model.php。

得益于 Yii 自带的类加载器,使用任何核心类都无需手动 require 对应文件——只要类名能被解析为可加载的路径即可。这一机制与下文“路径别名”一节紧密关联:每个根命名空间对应一个路径别名,加载器借此完成自动加载。迁移时只需把 1.1 的 Yii::import()、手动 include 全部删除,改为标准的 use 语句。

组件与对象:CComponent 一分为二

1.1 的 CComponent 在 2.0 中被拆分为两个类:

  • framework/base/BaseObject.php:轻量级基类,通过 getter/setter 提供**对象属性(Property)**能力。所谓属性即由 getLabel()/setLabel() 方法定义、以 $object->label 形式访问的成员,属性名不区分大小写;只有 getter 没有 setter 时属性为只读,赋值会抛异常。
  • framework/base/Component.php:继承自 BaseObject,额外支持**事件(Event)与行为(Behavior)**两大特性。其类注释明确说明:Component 在 BaseObject 的属性能力之上提供事件和行为能力。

选择依据很简单:如果你的类不需要事件和行为,就用 BaseObject 作为基类——例如纯粹的数据结构类。这能避免不必要的开销,也让类的职责更清晰。从源码看,Component 内部维护了 _events、_eventWildcards、_behaviors 三份内部状态(见 framework/base/Component.php),这正是它比 BaseObject 重的原因。

对象配置:构造器约定与初始化生命周期

BaseObject 引入了统一的对象配置机制。任何子类如果需要声明构造器,必须遵循以下约定(最后一个参数是配置数组,且必须在构造器末尾调用父类构造器):

class MyClass extends \yii\base\BaseObject
{
    public function __construct($param1, $param2, $config = [])
    {
        // ... 应用配置之前的初始化

        parent::__construct($config);
    }

    public function init()
    {
        parent::init();

        // ... 应用配置之后的初始化
    }
}

上述代码中,构造器的最后一个参数必须是配置数组,包含用于初始化属性的键值对。你可以重写 init() 方法执行需要在配置应用之后完成的初始化工作。

从 framework/base/BaseObject.php 的构造器实现可以印证这一生命周期:构造器先调用 Yii::configure($this, $config) 应用配置,再调用 $this->init()。因此完整的对象生命周期为:类构造器执行 → 依据配置初始化属性 → 调用 init() 方法。BaseObject 的类注释(framework/base/BaseObject.php)明确推荐在 init() 中做初始化,因为此时配置已全部就位。

遵循该约定后,你就可以用配置数组创建并配置新对象:

$object = Yii::createObject([
    'class' => 'MyClass',
    'property1' => 'abc',
    'property2' => 'cde',
], [$param1, $param2]);

关于配置机制的更多细节,参见 docs/guide-fr/concept-configurations.md。

事件:从 on 方法到任意事件名

1.1 中事件必须通过预定义的 on 方法(如 onBeforeSave)创建;2.0 则允许使用任意事件名。触发事件调用 trigger() 方法:

$event = new \yii\base\Event;
$component->trigger($eventName, $event);

绑定处理器用 on() 方法,解绑用 off():

$component->on($eventName, $handler);
// 解绑处理器:
// $component->off($eventName, $handler);

2.0 事件能力有大量增强,从 framework/base/Component.php 的源码可以看到:

  • 处理器可以是匿名函数、对象方法、静态类方法或全局函数四种形式;
  • 事件名区分大小写,且在类内必须唯一;
  • 支持通配符事件名(_eventWildcards,自 2.0.14 起);
  • 绑定时可附带额外数据 $data,处理器内通过 $event->data 访问;
  • 甚至可以在组件配置数组中直接声明 'on add' => function ($event) {...} 形式的处理器。

事件系统的详细用法参见 docs/guide-fr/concept-events.md。

路径别名:统一以 @ 开头并关联命名空间

2.0 将路径别名(Path Alias)的使用范围扩展到文件/目录路径与 URL,并强制要求别名以 @ 字符开头,以区别于普通路径和 URL。例如别名 @yii 指向 Yii 的安装目录。别名在 Yii 核心代码的大多数地方都受支持——比如 yii\caching\FileCache::cachePath 既可以接收路径别名,也可以接收普通目录路径。

路径别名与类命名空间紧密关联。建议为每个根命名空间定义一个路径别名,这样无需额外配置即可使用 Yii 的类自动加载器。例如,因为 @yii 指向 Yii 安装目录,yii\web\Request 这样的类就能被自动加载。如果使用第三方库(如 Zend Framework),可以定义一个指向其安装目录的路径别名 @Zend,之后 Yii 就能自动加载该库中的任意类。

更多内容参见 docs/guide-fr/concept-aliases.md。

视图:$this 语义颠覆与渲染方式变化

2.0 中视图最显著的变化是:视图文件里的特殊变量 $this 不再指向当前控制器或组件,而是指向一个视图对象(类型为 yii\web\View,源码见 framework/web/View.php),它代表 MVC 模式中的视图部分。如果想在视图中访问控制器或组件,请使用 $this->context。

在视图中渲染另一个视图(局部视图)时,使用 $this->render() 而非 1.1 的 $this->renderPartial()。且 render() 方法返回渲染结果而非直接输出,因此必须显式 echo:

echo $this->render('_item', ['item' => $item]);

除了 PHP 作为主要模板语言,2.0 官方支持 Smarty 与 Twig 两个流行模板引擎,Prado 模板引擎不再支持。使用这些引擎需要配置应用的 view 组件,设置 View::$renderers 属性——framework/web/View.php 的注释给出了 'view' => <a href="https://link.gitcode.com/i/486a0e68d711e9095bbe432767ae7736" target="_blank">'theme' => ..., 'renderers' => [...]] 的配置骨架。详见 [docs/guide-fr/tutorial-template-engines.md。

模型:CFormModel 消亡与 scenarios() 的新范式

2.0 以 framework/base/Model.php 中的 yii\base\Model 作为模型基类,对应 1.1 的 CModel。CFormModel 被彻底删除,创建表单模型类时直接继承 yii\base\Model 即可。

2.0 引入新方法 scenarios() 来声明支持的场景,并指出在某场景下哪些属性需要被验证、是否被视为安全(可批量赋值)等:

public function scenarios()
{
    return [
        'backend' => ['email', 'role'],
        'frontend' => ['email', '!role'],
    ];
}

上面的代码声明了 backend 与 frontend 两个场景:backend 场景下 email 和 role 都是安全的,可以批量赋值;frontend 场景下只有 email 可以批量赋值,role 不可以(前缀 ! 表示不安全)。两个属性都需要用规则进行验证。

rules() 方法仍然用于声明验证规则。注意:由于引入了 scenarios(),unsafe 验证器已经不存在了。在大多数情况下,如果 rules() 中的 'on' => [...] 已经完整指定了场景,且无需声明 unsafe 属性,你就不需要重写 scenarios()。

从源码看,framework/base/Model.php 的默认 scenarios() 实现会遍历所有验证器,根据其 on/except 声明自动汇总出各场景的激活属性列表——这正是“大多数情况无需重写”这一结论的底层依据。同时,yii\base\Model 还实现了属性声明、属性标签、批量赋值、基于场景的验证等常用功能,并触发 EVENT_BEFORE_VALIDATE / EVENT_AFTER_VALIDATE 事件(常量定义见 framework/base/Model.php)。

模型更多细节参见 docs/guide-fr/structure-models.md。

控制器:返回内容而非输出内容

2.0 使用 yii\web\Controller 作为控制器基类(对应 1.1 的 CController),yii\base\Action 是动作类的基类。

这些变化对代码最明显的影响是:控制器动作应当返回要渲染的内容,而不是直接输出:

public function actionView($id)
{
    $model = \app\models\Post::findOne($id);
    if ($model) {
        return $this->render('view', ['model' => $model]);
    } else {
        throw new \yii\web\NotFoundHttpException;
    }
}

注意 actionView 中 return $this->render(...) 与 throw new \yii\web\NotFoundHttpException 的组合——异常在此处承担了 1.1 中 $this->redirect() 之外的错误流控制职责。控制器细节参见 docs/guide-fr/structure-controllers.md。

组件(Widget):begin/end/widget 新语法

2.0 使用 yii\base\Widget 作为组件基类(对应 1.1 的 CWidget)。为了提升 IDE 对框架的支持度,2.0 引入了新的组件调用语法:静态方法 begin()、end()、widget(),用法如下:

use yii\widgets\Menu;
use yii\widgets\ActiveForm;

// 注意:必须使用 echo 来输出结果
echo Menu::widget(['items' => $items]);

// 传入数组来初始化对象属性
$form = ActiveForm::begin([
    'options' => ['class' => 'form-horizontal'],
    'fieldConfig' => ['inputOptions' => ['class' => 'input-xlarge']],
]);
... 表单输入字段 ...
ActiveForm::end();

widget() 用于一次性输出型组件,begin()/end() 用于需要包裹内容(如整个表单)的组件。从 framework/base/Widget.php 的源码可以看到,Widget 继承自 Component(因此拥有事件和行为能力),内部通过静态栈 $stack 维护 begin()/end() 的配对状态,并会触发 EVENT_INIT、EVENT_BEFORE_RUN、EVENT_AFTER_RUN 事件。详见 docs/guide-fr/structure-widgets.md。

主题:从 CThemeManager 到路径映射

2.0 的主题机制与 1.1 完全不同:现在基于路径映射——将源视图文件路径映射到主题化视图文件路径。例如,若主题的路径映射为 ['/web/views' => '/web/themes/basic'],那么视图文件 /web/views/site/index.php 的主题化版本就是 /web/themes/basic/site/index.php。因此主题现在可以应用于任何视图文件,甚至包括在控制器或组件上下文之外渲染的视图。

另外,CThemeManager 组件不复存在,取而代之的是 theme 成为 view 应用组件的一个可配置属性(可在 framework/web/View.php 的组件配置示例中看到 'theme' => 'app\themes\MyTheme' 的写法)。详见 docs/guide-fr/output-theming.md。

控制台应用:命令式控制器与自动帮助

控制台应用现在像 Web 应用一样按控制器组织。控制台控制器需继承 yii\console\Controller(对应 1.1 的 CConsoleCommand),仓库中的实现见 framework/console/Controller.php。

执行控制台命令的格式为:

yii <route>

其中 <route> 是控制器路由(例如 sitemap/index)。额外的匿名参数会作为参数传给对应的控制器动作方法;命名参数则根据 Controller::options() 方法中的声明进行解析。框架入口脚本位于 framework/yii。

2.0 支持从注释块自动生成命令帮助信息,这让命令行工具的自文档化程度大幅提升。详见 docs/guide-fr/tutorial-console.md。

I18N:放弃内置格式化,拥抱 intl 与 i18n 组件

2.0 移除了内置的日期格式化与数字格式化功能,转而使用 PECL intl PHP 模块。这解释了前文 PHP 需求中为何强调 intl 扩展——它现在是国际化的基础设施。

消息翻译改由 i18n 应用组件负责。该组件管理一组消息源(message source),允许你根据消息分类使用不同的消息来源(例如数据库消息源与文件消息源并存)。详见 docs/guide-fr/tutorial-i18n.md。

动作过滤器:以行为(Behavior)方式实现

动作过滤器现在通过行为(Behavior)实现。要定义新的自定义过滤器,继承 yii\base\ActionFilter;要使用过滤器,则将其作为行为声明在控制器中。例如,要使用 yii\filters\AccessControl 过滤器,控制器中代码如下:

public function behaviors()
{
    return [
        'access' => [
            'class' => 'yii\filters\AccessControl',
            'rules' => [
                ['allow' => true, 'actions' => ['admin'], 'roles' => ['@']],
            ],
        ],
    ];
}

这段代码声明了一个名为 access 的行为:对于 admin 动作,允许已登录用户(roles 中的 @ 表示已认证用户)访问。框架内置的过滤器实现位于 framework/filters 目录。详见 docs/guide-fr/structure-filters.md。

资源(Assets):从 Asset Manager 到 Asset Bundle

2.0 引入了名为**资源包(Asset Bundle)**的新概念,取代 1.1 的资源管理器概念。资源包是目录中资源文件(JavaScript、CSS、图片等)的集合,每个包用一个继承 yii\web\AssetBundle 的类表示。通过 AssetBundle::register() 注册资源包后,包内资源即可通过 Web 访问。与 1.1 不同,注册了资源包的页面会自动包含该包声明的 JavaScript 与 CSS 文件的引用,无需手动输出 <script> / <link> 标签。

资源包基类位于 framework/web/AssetBundle.php,框架自带的 JS 资源见 framework/assets。详见 docs/guide-fr/structure-assets.md。

助手类(Helpers):静态类的全面集结

2.0 引入了大量常用的静态助手类,包括但不限于:

助手类的完整清单与用法参见 docs/guide-fr/helper-overview.md。

表单:ActiveField 字段概念的引入

2.0 引入**字段(Field)**概念用于通过 yii\widgets\ActiveForm 构建表单。一个字段是标签、输入控件、错误消息和/或提示文本的容器,由 ActiveField 对象表示。使用字段可以让表单构建更干净:

<?php $form = yii\widgets\ActiveForm::begin(); ?>
    <?= $form->field($model, 'username') ?>
    <?= $form->field($model, 'password')->passwordInput() ?>
    <div class="form-group">
        <?= Html::submitButton('Login') ?>
    </div>
<?php yii\widgets\ActiveForm::end(); ?>

只需一行 $form->field($model, 'username'),标签、输入框、错误消息、提示文本就全部自动生成,这是 1.1 手写 HTML 时代难以想象的效率提升。表单构建详见 docs/guide-fr/input-forms.md。

查询构建器:三剑客合并为 Query 对象

1.1 中查询构建逻辑分散在 CDbCommand、CDbCriteria、CDbCommandBuilder 等多个类中。2.0 将数据库查询表示为 yii\db\Query 对象,并在幕后借助 yii\db\QueryBuilder 将其转化为 SQL 语句:

$query = new \yii\db\Query();
$query->select('id, name')
      ->from('user')
      ->limit(10);

$command = $query->createCommand();
$sql = $command->sql;
$rows = $command->queryAll();

select()、from()、limit() 等构建方法均返回 $this,支持链式调用;createCommand() 生成命令对象,通过其 sql 属性可查看最终 SQL,queryAll() 执行查询返回行数组。相关实现位于 framework/db/Query.php 与 framework/db/QueryBuilder.php。

更重要的是,这些查询构建方法在 Active Record 中同样可用。详见 docs/guide-fr/db-query-builder.md。

Active Record:CDbCriteria 谢幕与关系查询新纪元

2.0 对 Active Record 引入了大量修改,最明显的两点是查询构建与关系查询处理。

1.1 的 CDbCriteria 被 yii\db\ActiveQuery 取代。该类继承自 yii\db\Query(源码见 framework/db/ActiveQuery.php),因此继承了全部查询构建方法。通过 ActiveRecord::find() 即可开始构建查询:

// 获取所有 *活跃* 客户并按 ID 排序:
$customers = Customer::find()
    ->where(['status' => $active])
    ->orderBy('id')
    ->all();

关系声明:getter 取代 relations()

声明关系只需定义一个返回 ActiveQuery 对象的 getter 方法,该 getter 定义的属性名即关系名。1.1 需要在集中的 relations() 方法中声明,2.0 则内联在类中:

class Customer extends \yii\db\ActiveRecord
{
    public function getOrders()
    {
        return $this->hasMany('Order', ['customer_id' => 'id']);
    }
}

之后可用 $customer->orders 访问该客户的订单,也可以带自定义条件进行即时关系查询:

$orders = $customer->getOrders()->andWhere('status=1')->all();

预加载(Eager Loading)策略变化

预加载关系时,2.0 与 1.1 的处理方式不同:1.1 会创建一条 JOIN 查询同时选取主记录与关联记录;2.0 执行两条 SQL 而不使用 JOIN——第一条取回主记录,第二条依据主记录的主键过滤取回关联记录。这一改变避免了 JOIN 在大数据集上的笛卡尔积膨胀问题,是 framework/db/ActiveQuery.php 中 ActiveQueryTrait / ActiveRelationTrait 组合实现的。

asArray():海量数据的数组化查询

如果希望返回大量记录,可以在构建查询时链式调用 asArray(),让结果以数组而非 ActiveRecord 对象返回,从而显著降低 CPU 与内存消耗:

$customers = Customer::find()->asArray()->all();

默认值设置与构造器

另一个变化是:不能再通过公有属性定义属性默认值。如有需要,应在记录类的 init() 方法中设置:

public function init()
{
    parent::init();
    $this->status = self::STATUS_NEW;
}

1.1 中重写 ActiveRecord 类构造器存在一些问题,2.0 中已不存在。注意:当给构造器添加参数时,可能需要重写 ActiveRecord::instantiate() 方法。

关系查询的扩展能力

从 framework/db/ActiveQuery.php 的注释可见,2.0 的查询还支持 with()、joinWith()、indexBy()、via()/viaTable() 关联中间表、inverseOf() 反向关系、onCondition() 关联条件等丰富能力,以及 batch()/each() 批量查询迭代器。这些都远超 1.1 的能力范围。详见 docs/guide-fr/db-active-record.md。

Active Record 行为:CActiveRecordBehavior 谢幕

2.0 删除了 CActiveRecordBehavior 基类。要创建 Active Record 行为,需直接继承 yii\base\Behavior。如果行为类需要响应所有者的事件,必须像下面这样重写 events() 方法:

namespace app\components;

use yii\db\ActiveRecord;
use yii\base\Behavior;

class MyBehavior extends Behavior
{
    // ...

    public function events()
    {
        return [
            ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',
        ];
    }

    public function beforeValidate($event)
    {
        // ...
    }
}

events() 返回事件名到处理器方法的映射,事件常量(如 ActiveRecord::EVENT_BEFORE_VALIDATE)在 framework/db/ActiveRecord.php 中定义。这也呼应了前文“事件从 on 方法到任意事件名”的变化——行为与事件在新框架中是同一套机制的两个侧面。

用户与身份:CUserIdentity 谢幕,IdentityInterface 登场

1.1 的 CWebUser 现由 yii\web\User 取代,CUserIdentity 类不复存在。取而代之的是实现 yii\web\IdentityInterface,它使用起来更加直接。高级项目模板(Advanced Project Template)提供了实现示例。

从 framework/web/IdentityInterface.php 的注释可以看到该接口的典型实现模式:用户模型(通常是 User ActiveRecord 类)实现 findIdentity()、findIdentityByAccessToken()、getId()、getAuthKey()、validateAuthKey() 五个方法。而且并非所有方法都必须实现:纯无状态 RESTful 应用只需 findIdentityByAccessToken() 与 getId(),其余留空即可;仅用会话认证的应用则除 findIdentityByAccessToken() 外都需实现。

认证与授权细节参见 docs/guide-fr/security-authentication.md 与 docs/guide-fr/security-authorization.md。

URL 管理:可选参数与路由命名约定

2.0 的 URL 管理与 1.1 类似,但一个重要增强是支持可选参数。例如,声明如下规则后,post/popular 与 post/1/popular 都能匹配;1.1 中这需要两条规则才能实现:

[
    'pattern' => 'post/<page:\d+>/<tag>',
    'route' => 'post/index',
    'defaults' => ['page' => 1],
]

defaults 中的 'page' => 1 使得 page 参数在 URL 中缺省时取默认值 1,从而让两个 URL 命中同一路由。规则对象由 framework/web/UrlRule.php 实现,支持 PARSING_ONLY / CREATION_ONLY 模式、HTTP 动词约束('PUT post/<id:\d+>' => 'post/update' 快捷写法)、RESTful 路由等进阶能力(见 framework/web/UrlManager.php 的注释与 rules 属性说明)。详见 docs/guide-fr/runtime-routing.md。

路由命名约定也有一个重要变化:控制器和动作的驼峰命名现在转换为全小写、以连字符分隔的形式,例如 CamelCaseController 的控制器 ID 为 camel-case。详见 docs/guide-fr/structure-controllers.md 中关于 controller IDs 与 action IDs 的章节(英文版见 docs/guide/structure-controllers.md)。

迁移检查清单与后续路径

综合全文,从 1.1 迁移到 2.0 的核心动作可以收敛为一张清单:

迁移维度 1.1 旧写法 2.0 新写法
类组织 CController、CComponent 等 C 前缀类名 + Yii::import() 命名空间类(yii\web\Controller 等)+ use 语句 + 自动加载
组件体系 CComponent 数据类用 BaseObject,需要事件/行为用 Component
对象配置 手动赋值 构造器 $config 尾参 + Yii::createObject() + init()
事件 onBeforeSave 等 on 方法 任意事件名 + trigger() / on() / off()
视图 $this 指向控制器;renderPartial() 直接输出 $this 指向视图对象;$this->render() 需 echo
模型 CModel + CFormModel + unsafe 验证器 yii\base\Model + scenarios() + ! 前缀标记不安全属性
控制器 动作内 echo 输出 动作 return 渲染结果
组件 CWidget 手动实例化 Widget::widget() / begin() / end() 静态调用
查询 CDbCommand / CDbCriteria / CDbCommandBuilder yii\db\Query + 链式方法 + QueryBuilder
Active Record relations() 集中声明;JOIN 预加载;公有属性默认值 getter 声明关系;双 SQL 预加载;init() 设置默认值;asArray()
用户认证 CWebUser + CUserIdentity yii\web\User + IdentityInterface
主题 CThemeManager view 组件 theme 属性 + 路径映射
资源 Asset Manager AssetBundle + register()

如果你有希望与 Yii 2.0 共存的 1.1 遗留代码,可以参考 docs/guide-fr/tutorial-yii-integration.md(英文版对应 docs/guide/tutorial-yii-integration.md)。

需要强调的是,2.0 引入的新特性远不止本文覆盖的这些。强烈建议通读 docs/guide-fr/README.md 所指向的完整权威指南(definitive guide)——你过去需要自己动手开发的某些功能,很可能已经成为 2.0 核心代码的一部分。

登录后查看全文
yii2