Yii 2.0與Yii 1.1 的區別

2.0 版框架是完全重寫的,在 1.1 和 2.0 兩個版本之間存在相當多差異。因此從 1.1 版升級並不像小版本間的跨越那麼簡單,通過本指南你將會了解兩個版本間主要的不同之處。

如果你之前沒有用過 Yii 1.1,可以跳過本章,直接從"入門篇"開始讀起。

請注意,Yii 2.0 引入了很多本章並沒有涉及到的新功能。強烈建議你通讀整部權威指南來了解所有新特性。這樣有可能會發現一些以前你要自己開發的功能,而現在已經被包含在覈心代碼中了。

安裝

Yii 2.0 完全擁抱 Composer,它是事實上的 PHP 依賴管理工具。核心框架以及擴展的安裝都通過 Composer 來處理。想要了解更多如何安裝 Yii 2.0 請參閱本指南的 安裝 Yii 章節。如果你想創建新擴展,或者把你已有的 Yii 1.1 的擴展改寫成兼容 2.0 的版本,你可以參考 創建擴展 章節。

PHP 需求

Yii 2.0 需要 PHP 5.4 或更高版本,該版本相對於 Yii 1.1 所需求的 PHP 5.2 而言有巨大的改進。因此在語言層面上有很多的值得注意的不同之處。下面是 PHP 層的主要變化彙總:

命名空間

Yii 2.0 裏最明顯的改動就數命名空間的使用了。幾乎每一個核心類都引入了命名空間,比如 yii\web\Request。1.1 版類名前綴 “C” 已經不再使用。當前的命名方案與目錄結構相吻合。例如,yii\web\Request 就表明對應的類文件是 Yii 框架文件夾下的 web/Request.php 文件。

有了 Yii 的類自動加載器,你可以直接使用全部核心類而不需要顯式包含具體文件。

組件(Component)與對象(Object)

Yii 2.0 把 1.1 中的 CComponent 類拆分成了兩個類:[[yii\base\Object]] 和 [[yii\base\Component]]。[[yii\base\Object|Object]] 類是一個輕量級的基類,你可以通過 getters 和 setters 來定義對象的屬性。[[yii\base\Component|Component]] 類繼承自 [[yii\base\Object|Object]],同時進一步支持 事件 行爲

如果你不需要用到事件或行爲,應該考慮使用 [[yii\base\Object|Object]] 類作爲基類。這種類通常用來表示基本的數據結構。

對象的配置

[[yii\base\Object|Object]] 類引入了一種統一對象配置的方法。所有 [[yii\base\Object|Object]] 的子類都應該用以下方法聲明它的構造方法(如果需要的話),以正確配置它自身:

class MyClass extends \yii\base\Object
{
    public function __construct($param1, $param2, $config = [])
    {
        // ... 配置生效前的初始化過程

        parent::__construct($config);
    }

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

        // ... 配置生效後的初始化過程
    }
}

在上面的例子裏,構造方法的最後一個參數必須傳入一個配置數組,包含一系列用於在方法結尾初始化相關屬性的鍵值對。你可以重寫 [[yii\base\Object::init()|init()]] 方法來執行一些需要在配置生效後進行的初始化工作。

你可以通過遵循以下約定俗成的編碼習慣,來使用配置數組創建並配置新的對象:

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

更多有關配置的細節可以在配置章節找到。

事件(Event)

在 Yii 1 中,通常通過定義 on 開頭的方法(例如 onBeforeSave)來創建事件。而在 Yii 2 中,你可以使用任意的事件名了。同時通過調用 [[yii\base\Component::trigger()|trigger()]] 方法來觸發相關事件:

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

要給事件附加一個事件事件處理器,需要使用 [[yii\base\Component::on()|on()]] 方法:

$component->on($eventName, $handler);
// 解除事件處理器,使用 off 方法:
// $component->off($eventName, $handler);

事件功能還有更多增強之處。要了解它們,請查看事件章節。

路徑別名(Path Alias)

Yii 2.0 將路徑別名的應用擴大至文件/目錄路徑和 URL。Yii 2.0 中路徑別名必須以 @ 符號開頭,以區別於普通文件目錄路徑或 URL。例如 @yii 就是指向 Yii 安裝目錄的別名。絕大多數 Yii 核心代碼都支持別名。例如 [[yii\caching\FileCache::cachePath]] 就同時支持路徑別名或普通的目錄地址。

路徑別名也和類的命名空間密切相關。建議給每一個根命名空間定義一個路徑別名,從而無須額外配置,便可啓動 Yii 的類自動加載機制。例如,因爲有 @yii 指向 Yii 安裝目錄,那類似 yii\web\Request 的類就能被 Yii 自動加載。同理,若你用了一個第三方的類庫,如 Zend Framework,你只需定義一個名爲 @Zend 的路徑別名指向該框架的安裝目錄。之後 Yii 就可以自動加載任意 Zend Framework 中的類了。

更多路徑別名信息請參閱路徑別名章節。

視圖(View)

Yii 2 中視圖最明顯的改動是視圖內的特殊變量 $this 不再指向當前控制器或小部件,而是指向視圖對象,它是 2.0 中引入的全新概念。視圖對象爲 [[yii\web\View]] 的實例,他代表了 MVC 模式中的視圖部分。如果你想要在視圖中訪問一個控制器或小部件,可以使用 $this->context

要在其他視圖裏渲染一個局部視圖,使用 $this->render(),而不是 $this->renderPartial()render() 現在只返回渲染結果,而不是直接顯示它,所以現在你必須顯式地把它 echo 出來。像這樣:

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

除了使用 PHP 作爲主要的模板語言,Yii 2.0 也裝備了兩種流行模板引擎的官方支持:Smarty 和 Twig。過去的 Prado 模板引擎不再被支持。要使用這些模板引擎,你需要配置 view 應用組件,給它設置 [[yii\base\View::$renderers|View::$renderers]] 屬性。具體請參閱模板引擎章節。

模型(Model)

Yii 2.0 使用 [[yii\base\Model]] 作爲模型基類,類似於 1.1 的 CModelCFormModel 被完全棄用了,現在要創建表單模型類,可以通過繼承 [[yii\base\Model]] 類來實現。

Yii 2.0 引進了名爲 [[yii\base\Model::scenarios()|scenarios()]] 的新方法來聲明支持的場景,並指明在哪個場景下某屬性必須經過驗證,可否被視爲安全值等等。如:

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

上面的代碼聲明瞭兩個場景:backendfrontend 。對於 backend 場景,emailrole 屬性值都是安全的,且能進行批量賦值。對於 frontend 場景,email 能批量賦值而 role 不能。 emailrole 都必須通過規則驗證。

[[yii\base\Model::rules()|rules()]] 方法仍用於聲明驗證規則。注意,由於引入了 [[yii\base\Model::scenarios()|scenarios()]],現在已經沒有 unsafe 驗證器了。

大多數情況下,如果 [[yii\base\Model::rules()|rules()]] 方法內已經完整地指定場景了,那就不必覆寫 [[yii\base\Model::scenarios()|scenarios()]],也不必聲明 unsafe 屬性值。

要了解更多有關模型的細節,請參考模型章節。

控制器(Controller)

Yii 2.0 使用 [[yii\web\Controller]] 作爲控制器的基類,它類似於 1.1 的 CController。使用 [[yii\base\Action]] 作爲操作類的基類。

這些變化最明顯的影響是,當你在寫控制器操作的代碼時,應該返回(return)要渲染的內容而不是輸出(echo)它:

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

請查看控制器(Controller)章節瞭解有關控制器的更多細節。

小部件(Widget)

Yii 2.0 使用 [[yii\base\Widget]] 作爲小部件基類,類似於 1.1 的 CWidget

爲了讓框架獲得更好的 IDE 支持,Yii 2.0 引進了一個調用小部件的新語法。包含 [[yii\base\Widget::begin()|begin()]],[[yii\base\Widget::end()|end()]] 和 [[yii\base\Widget::widget()|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();

更多細節請參閱小部件章節。

主題(Theme)

2.0 主題的運作方式跟以往完全不同了。它們現在基於路徑映射機制,該機制會把一個源視圖文件的路徑映射到一個主題視圖文件路徑。舉例來說,如果路徑映射爲 ['/web/views' => '/web/themes/basic'],那麼 /web/views/site/index.php 視圖經過主題修飾的版本就會是 /web/themes/basic/site/index.php。也因此讓主題現在可以應用在任何視圖文件之上,甚至是渲染控制器上下文環境之外的視圖文件或小部件。

同樣,CThemeManager 組件已經被移除了。取而代之的 theme 成爲了 view 應用組件的一個可配置屬性。

更多細節請參考主題章節。

控制檯應用(Console Application)

控制檯應用現在如普通的 Web 應用程序一樣,由控制器組成,控制檯的控制器繼承自 [[yii\console\Controller]],類似於 1.1 的 CConsoleCommand

運行控制檯命令使用 yii <route>,其中 <route> 代表控制器的路由(如 sitemap/index)。額外的匿名參數傳遞到對應的控制器操作方法,而有名的參數根據 [[yii\console\Controller::options()]] 的聲明來解析。

Yii 2.0 支持基於代碼註釋自動生成相的關命令行幫助(help)信息。

更多細節請參閱控制檯命令章節。

國際化(I18N)

Yii 2.0 移除了原來內置的日期格式器和數字格式器,爲了支持 PECL intl PHP module(PHP 的國際化擴展)的使用。

消息翻譯現在由 i18n 應用組件執行。該組件管理一系列消息源,允許使用基於消息類別的不同消息源。

更多細節請參閱國際化(Internationalization)章節。

操作過濾器(Action Filters)

操作的過濾現在通過行爲(behavior)來實現。要定義一個新的,自定義的過濾器,請繼承 [[yii\base\ActionFilter]] 類。要使用一個過濾器,需要把過濾器類作爲一個 behavior 綁定到控制器上。例如,要使用 [[yii\filters\AccessControl]] 過濾器,你需要在控制器內添加如下代碼:

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

更多細節請參考過濾器章節。

前端資源(Assets)

Yii 2.0 引入了一個新的概念,稱爲資源包(Asset Bundle),以代替 1.1 的腳本包概念。

一個資源包是一個目錄下的資源文件集合(如 JavaScript 文件、CSS 文件、圖片文件等)。每一個資源包被表示爲一個類,該類繼承自 [[yii\web\AssetBundle]]。用 [[yii\web\AssetBundle::register()]] 方法註冊一個資源包後,就使它的資源可被 Web 訪問了,註冊了資源包的頁面會自動包含和引用資源包內指定的 JS 和 CSS 文件。

更多細節請參閱 前端資源管理(Asset) 章節。

助手類(Helpers)

Yii 2.0 很多常用的靜態助手類,包括:

  • [[yii\helpers\Html]]
  • [[yii\helpers\ArrayHelper]]
  • [[yii\helpers\StringHelper]]
  • [[yii\helpers\FileHelper]]
  • [[yii\helpers\Json]]

請參考助手一覽 章節來了解更多。

表單

Yii 2.0 引進了表單欄(field)的概念,用來創建一個基於 [[yii\widgets\ActiveForm]] 的表單。一個表單欄是一個由標籤、輸入框、錯誤消息(可能還有提示文字)組成的容器,被表示爲一個 [[yii\widgets\ActiveField|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(); ?>

請參考創建表單章節來了解更多細節。

查詢生成器(Query Builder)

Yii 1.1 中,查詢語句的生成分散在多個類中,包括 CDbCommandCDbCriteria 以及 CDbCommandBuilder。Yii 2.0 以 [[yii\db\Query|Query]] 對象的形式表示一個數據庫查詢,這個對象使用 [[yii\db\QueryBuilder|QueryBuilder]] 在幕後生成 SQL 語句。例如:

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

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

最重要的是,這些查詢生成方法還可以和活動記錄配合使用。

請參考查詢生成器(Query Builder)章節瞭解更多內容。

活動記錄(Active Record)

Yii 2.0 的活動記錄改動了很多。兩個最顯而易見的改動分別涉及查詢語句的生成(query building)和關聯查詢的處理(relational query handling)。

1.1 中的 CDbCriteria 類在 Yii 2 中被 [[yii\db\ActiveQuery]] 所替代。這個類是繼承自 [[yii\db\Query]],因此也繼承了所有查詢生成方法。開始拼裝一個查詢可以調用 [[yii\db\ActiveRecord::find()]] 方法進行:

// 檢索所有“活動的”客戶和訂單,並以 ID 排序:
$customers = Customer::find()
    ->where(['status' => $active])
    ->orderBy('id')
    ->all();

要聲明一個關聯關係,只需簡單地定義一個 getter 方法來返回一個 [[yii\db\ActiveQuery|ActiveQuery]] 對象。getter 方法定義的屬性名代表關聯表名稱。如,以下代碼聲明瞭一個名爲 orders 的關係(1.1 中必須在 relations() 方法內聲明關係):

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();

當貪婪加載一段關聯關係時,Yii 2.0 和 1.1 的運作機理並不相同。具體來說,在 1.1 中使用一條 JOIN 語句同時查詢主表和關聯表記錄。在 Yii 2.0 中會使用兩個沒有 JOIN 的 SQL 語句:第一條語句取回主表記錄,第二條通過主表記錄經主鍵篩選後查詢關聯表記錄。

當生成返回大量記錄的查詢時,可以鏈式書寫 [[yii\db\ActiveQuery::asArray()|asArray()]] 方法,這樣會以數組的形式返回查詢結果,而不必返回[[yii\db\ActiveRecord|ActiveRecord]] 對象,這能顯著降低因大量記錄讀取所消耗的 CPU 時間和內存。如:

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

另一個改變是你不能再通過公共變量定義屬性(Attribute)的默認值了。如果你需要這麼做的話,可以在你的記錄類的 init 方法中設置它們。

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

曾幾何時,在 1.1 中重寫一個活動記錄類的構造方法會導致一些問題。它們不會在 2.0 中出現了。需要注意的是,如果你需要在構造方法中添加一些參數,恐怕必須重寫 [[yii\db\ActiveRecord::instantiate()]] 方法。

活動記錄方面還有很多其他的變化與改進,請參考活動記錄章節以瞭解更多細節。

活動記錄行爲(Active Record Behaviors)

在 2.0 中遺棄了活動記錄行爲基類 CActiveRecordBehavior。如果你想創建活動記錄行爲,需要直接繼承 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)
    {
        // ...
    }
}

用戶及身份驗證接口(IdentityInterface)

1.1 中的 CWebUser 類現在被 [[yii\web\User]] 所取代,隨之 CUserIdentity 類也不在了。與之相對的,爲達到相同目的,你可以實現 [[yii\web\IdentityInterface]] 接口,它使用起來更直觀。在高級應用模版裏提供了一個這樣的一個例子。

要了解更多細節請參考認證(Authentication)授權(Authorization)以及高級應用模版 這三個章節。

URL 管理

Yii 2.0 的 URL 管理跟 1.1 中很像。一個主要的改進是現在的 URL 管理支持可選參數了。比如,如果你在 2.0 中定義了一個下面這樣的規則,那麼它可以同時匹配 post/popularpost/1/popular 兩種 URL。而在 1.1 中爲達成相同效果,必須要使用兩條規則。

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

請參考URL 解析和生成 章節,以瞭解更多細節。.

同時使用 Yii 1.1 和 2.x

如果你有一些遺留的 Yii 1.1 代碼,需要跟 Yii 2.0 一起使用,可以參考 1.1 和 2.0 共用章節。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章