?
このドキュメントでは、 php中國(guó)語(yǔ)ネットマニュアル リリース
2.0 版框架是完全重寫(xiě)的,在 1.1 和 2.0 兩個(gè)版本之間存在相當(dāng)多差異。因此從 1.1 版升級(jí)并不像小版本間的跨越那么簡(jiǎn)單,通過(guò)本指南你將會(huì)了解兩個(gè)版本間主要的不同之處。
如果你之前沒(méi)有用過(guò) Yii 1.1,可以跳過(guò)本章,直接從"入門篇"開(kāi)始讀起。
請(qǐng)注意,Yii 2.0 引入了很多本章并沒(méi)有涉及到的新功能。強(qiáng)烈建議你通讀整部權(quán)威指南來(lái)了解所有新特性。這樣有可能會(huì)發(fā)現(xiàn)一些以前你要自己開(kāi)發(fā)的功能,而現(xiàn)在已經(jīng)被包含在核心代碼中了。
Yii 2.0 完全擁抱?Composer,它是事實(shí)上的 PHP 依賴管理工具。核心框架以及擴(kuò)展的安裝都通過(guò) Composer 來(lái)處理。想要了解更多如何安裝 Yii 2.0 請(qǐng)參閱本指南的?安裝 Yii?章節(jié)。如果你想創(chuàng)建新擴(kuò)展,或者把你已有的 Yii 1.1 的擴(kuò)展改寫(xiě)成兼容 2.0 的版本,你可以參考?創(chuàng)建擴(kuò)展?章節(jié)。
Yii 2.0 需要 PHP 5.4 或更高版本,該版本相對(duì)于 Yii 1.1 所需求的 PHP 5.2 而言有巨大的改進(jìn)。因此在語(yǔ)言層面上有很多的值得注意的不同之處。下面是 PHP 層的主要變化匯總:
[...元素...]
?用于取代?array(...元素...)
<?=
,自 PHP 5.4 起總會(huì)被識(shí)別并且合法,無(wú)論 short_open_tag 的設(shè)置是什么,可以安全使用。intl
?來(lái)支持國(guó)際化的相關(guān)功能。Yii 2.0 里最明顯的改動(dòng)就數(shù)命名空間的使用了。幾乎每一個(gè)核心類都引入了命名空間,比如?yii\web\Request
。1.1 版類名前綴 “C” 已經(jīng)不再使用。當(dāng)前的命名方案與目錄結(jié)構(gòu)相吻合。例如,yii\web\Request
?就表明對(duì)應(yīng)的類文件是 Yii 框架文件夾下的?web/Request.php
?文件。
有了 Yii 的類自動(dòng)加載器,你可以直接使用全部核心類而不需要顯式包含具體文件。
Yii 2.0 把 1.1 中的?CComponent
?類拆分成了兩個(gè)類:yii\base\Object 和 yii\base\Component。yii\base\Object 類是一個(gè)輕量級(jí)的基類,你可以通過(guò) getters 和 setters 來(lái)定義對(duì)象的屬性。yii\base\Component 類繼承自 yii\base\Object,同時(shí)進(jìn)一步支持?事件?和?行為。
如果你不需要用到事件或行為,應(yīng)該考慮使用 yii\base\Object 類作為基類。這種類通常用來(lái)表示基本的數(shù)據(jù)結(jié)構(gòu)。
yii\base\Object 類引入了一種統(tǒng)一對(duì)象配置的方法。所有 yii\base\Object 的子類都應(yīng)該用以下方法聲明它的構(gòu)造方法(如果需要的話),以正確配置它自身:
class MyClass extends \yii\base\Object
{
public function __construct($param1, $param2, $config = [])
{
// ... 配置生效前的初始化過(guò)程
parent::__construct($config);
}
public function init()
{
parent::init();
// ... 配置生效后的初始化過(guò)程
}
}
在上面的例子里,構(gòu)造方法的最后一個(gè)參數(shù)必須傳入一個(gè)配置數(shù)組,包含一系列用于在方法結(jié)尾初始化相關(guān)屬性的鍵值對(duì)。你可以重寫(xiě) yii\base\Object::init() 方法來(lái)執(zhí)行一些需要在配置生效后進(jìn)行的初始化工作。
你可以通過(guò)遵循以下約定俗成的編碼習(xí)慣,來(lái)使用配置數(shù)組創(chuàng)建并配置新的對(duì)象:
$object = Yii::createObject([
'class' => 'MyClass',
'property1' => 'abc',
'property2' => 'cde',
], [$param1, $param2]);
更多有關(guān)配置的細(xì)節(jié)可以在配置章節(jié)找到。
在 Yii 1 中,通常通過(guò)定義?on
?開(kāi)頭的方法(例如?onBeforeSave
)來(lái)創(chuàng)建事件。而在 Yii 2 中,你可以使用任意的事件名了。同時(shí)通過(guò)調(diào)用 yii\base\Component::trigger() 方法來(lái)觸發(fā)相關(guān)事件:
$event = new \yii\base\Event;
$component->trigger($eventName, $event);
要給事件附加一個(gè)事件事件處理器,需要使用 yii\base\Component::on() 方法:
$component->on($eventName, $handler);
// 解除事件處理器,使用 off 方法:
// $component->off($eventName, $handler);
事件功能還有更多增強(qiáng)之處。要了解它們,請(qǐng)查看事件章節(jié)。
Yii 2.0 將路徑別名的應(yīng)用擴(kuò)大至文件/目錄路徑和 URL。Yii 2.0 中路徑別名必須以?@
?符號(hào)開(kāi)頭,以區(qū)別于普通文件目錄路徑或 URL。例如?@yii
?就是指向 Yii 安裝目錄的別名。絕大多數(shù) Yii 核心代碼都支持別名。例如 yii\caching\FileCache::cachePath 就同時(shí)支持路徑別名或普通的目錄地址。
路徑別名也和類的命名空間密切相關(guān)。建議給每一個(gè)根命名空間定義一個(gè)路徑別名,從而無(wú)須額外配置,便可啟動(dòng) Yii 的類自動(dòng)加載機(jī)制。例如,因?yàn)橛?@yii
?指向 Yii 安裝目錄,那類似?yii\web\Request
?的類就能被 Yii 自動(dòng)加載。同理,若你用了一個(gè)第三方的類庫(kù),如 Zend Framework,你只需定義一個(gè)名為?@Zend
?的路徑別名指向該框架的安裝目錄。之后 Yii 就可以自動(dòng)加載任意 Zend Framework 中的類了。
更多路徑別名信息請(qǐng)參閱路徑別名章節(jié)。
Yii 2 中視圖最明顯的改動(dòng)是視圖內(nèi)的特殊變量?$this
?不再指向當(dāng)前控制器或小部件,而是指向視圖對(duì)象,它是 2.0 中引入的全新概念。視圖對(duì)象為 yii\web\View 的實(shí)例,他代表了 MVC 模式中的視圖部分。如果你想要在視圖中訪問(wèn)一個(gè)控制器或小部件,可以使用?$this->context
。
要在其他視圖里渲染一個(gè)局部視圖,使用?$this->render()
,而不是?$this->renderPartial()
。render()
?現(xiàn)在只返回渲染結(jié)果,而不是直接顯示它,所以現(xiàn)在你必須顯式地把它?echo?出來(lái)。像這樣:
echo $this->render('_item', ['item' => $item]);
除了使用 PHP 作為主要的模板語(yǔ)言,Yii 2.0 也裝備了兩種流行模板引擎的官方支持:Smarty 和 Twig。過(guò)去的 Prado 模板引擎不再被支持。要使用這些模板引擎,你需要配置?view
?應(yīng)用組件,給它設(shè)置 yii\base\View::$renderers 屬性。具體請(qǐng)參閱模板引擎章節(jié)。
Yii 2.0 使用 yii\base\Model 作為模型基類,類似于 1.1 的?CModel
?。CFormModel
?被完全棄用了,現(xiàn)在要?jiǎng)?chuàng)建表單模型類,可以通過(guò)繼承 yii\base\Model 類來(lái)實(shí)現(xiàn)。
Yii 2.0 引進(jìn)了名為 yii\base\Model::scenarios() 的新方法來(lái)聲明支持的場(chǎng)景,并指明在哪個(gè)場(chǎng)景下某屬性必須經(jīng)過(guò)驗(yàn)證,可否被視為安全值等等。如:
public function scenarios()
{
return [
'backend' => ['email', 'role'],
'frontend' => ['email', '!role'],
];
}
上面的代碼聲明了兩個(gè)場(chǎng)景:backend
?和?frontend
?。對(duì)于?backend
?場(chǎng)景,email
?和?role
?屬性值都是安全的,且能進(jìn)行批量賦值。對(duì)于?frontend
?場(chǎng)景,email
?能批量賦值而?role
?不能。?email
?和?role
?都必須通過(guò)規(guī)則驗(yàn)證。
yii\base\Model::rules() 方法仍用于聲明驗(yàn)證規(guī)則。注意,由于引入了 yii\base\Model::scenarios(),現(xiàn)在已經(jīng)沒(méi)有?unsafe
?驗(yàn)證器了。
大多數(shù)情況下,如果 yii\base\Model::rules() 方法內(nèi)已經(jīng)完整地指定場(chǎng)景了,那就不必覆寫(xiě) yii\base\Model::scenarios(),也不必聲明unsafe
?屬性值。
要了解更多有關(guān)模型的細(xì)節(jié),請(qǐng)參考模型章節(jié)。
Yii 2.0 使用 yii\web\Controller 作為控制器的基類,它類似于 1.1 的?CController
。使用 yii\base\Action 作為操作類的基類。
這些變化最明顯的影響是,當(dāng)你在寫(xiě)控制器操作的代碼時(shí),應(yīng)該返回(return)要渲染的內(nèi)容而不是輸出(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;
}
}
請(qǐng)查看控制器(Controller)章節(jié)了解有關(guān)控制器的更多細(xì)節(jié)。
Yii 2.0 使用 yii\base\Widget 作為小部件基類,類似于 1.1 的?CWidget
。
為了讓框架獲得更好的 IDE 支持,Yii 2.0 引進(jìn)了一個(gè)調(diào)用小部件的新語(yǔ)法。包含 yii\base\Widget::begin(),yii\base\Widget::end() 和 yii\base\Widget::widget() 三個(gè)靜態(tài)方法,用法如下:
use yii\widgets\Menu;
use yii\widgets\ActiveForm;
// 注意必須 **"echo"** 結(jié)果以顯示內(nèi)容
echo Menu::widget(['items' => $items]);
// 傳遞一個(gè)用于初始化對(duì)象屬性的數(shù)組
$form = ActiveForm::begin([
'options' => ['class' => 'form-horizontal'],
'fieldConfig' => ['inputOptions' => ['class' => 'input-xlarge']],
]);
... 表單輸入欄都在這里 ...
ActiveForm::end();
更多細(xì)節(jié)請(qǐng)參閱小部件章節(jié)。
2.0 主題的運(yùn)作方式跟以往完全不同了。它們現(xiàn)在基于路徑映射機(jī)制,該機(jī)制會(huì)把一個(gè)源視圖文件的路徑映射到一個(gè)主題視圖文件路徑。舉例來(lái)說(shuō),如果路徑映射為?['/web/views' => '/web/themes/basic']
,那么?/web/views/site/index.php
?視圖經(jīng)過(guò)主題修飾的版本就會(huì)是?/web/themes/basic/site/index.php
。也因此讓主題現(xiàn)在可以應(yīng)用在任何視圖文件之上,甚至是渲染控制器上下文環(huán)境之外的視圖文件或小部件。
同樣,CThemeManager
?組件已經(jīng)被移除了。取而代之的?theme
?成為了?view
?應(yīng)用組件的一個(gè)可配置屬性。
更多細(xì)節(jié)請(qǐng)參考主題章節(jié)。
控制臺(tái)應(yīng)用現(xiàn)在如普通的 Web 應(yīng)用程序一樣,由控制器組成,控制臺(tái)的控制器繼承自 yii\console\Controller,類似于 1.1 的CConsoleCommand
。
運(yùn)行控制臺(tái)命令使用?yii <route>gt;
,其中?<route>
?代表控制器的路由(如?sitemap/index
)。額外的匿名參數(shù)傳遞到對(duì)應(yīng)的控制器操作方法,而有名的參數(shù)根據(jù) yii\console\Controller::options() 的聲明來(lái)解析。
Yii 2.0 支持基于代碼注釋自動(dòng)生成相的關(guān)命令行幫助(help)信息。
更多細(xì)節(jié)請(qǐng)參閱控制臺(tái)命令章節(jié)。
Yii 2.0 移除了原來(lái)內(nèi)置的日期格式器和數(shù)字格式器,為了支持?PECL intl PHP module(PHP 的國(guó)際化擴(kuò)展)的使用。
消息翻譯現(xiàn)在由?i18n
?應(yīng)用組件執(zhí)行。該組件管理一系列消息源,允許使用基于消息類別的不同消息源。
更多細(xì)節(jié)請(qǐng)參閱國(guó)際化(Internationalization)章節(jié)。
操作的過(guò)濾現(xiàn)在通過(guò)行為(behavior)來(lái)實(shí)現(xiàn)。要定義一個(gè)新的,自定義的過(guò)濾器,請(qǐng)繼承 yii\base\ActionFilter 類。要使用一個(gè)過(guò)濾器,需要把過(guò)濾器類作為一個(gè)?behavior
?綁定到控制器上。例如,要使用 yii\filters\AccessControl 過(guò)濾器,你需要在控制器內(nèi)添加如下代碼:
public function behaviors()
{
return [
'access' => [
'class' => 'yii\filters\AccessControl',
'rules' => [
['allow' => true, 'actions' => ['admin'], 'roles' => ['@']],
],
],
];
}
更多細(xì)節(jié)請(qǐng)參考過(guò)濾器章節(jié)。
Yii 2.0 引入了一個(gè)新的概念,稱為資源包(Asset Bundle),以代替 1.1 的腳本包概念。
一個(gè)資源包是一個(gè)目錄下的資源文件集合(如 JavaScript 文件、CSS 文件、圖片文件等)。每一個(gè)資源包被表示為一個(gè)類,該類繼承自 yii\web\AssetBundle。用 yii\web\AssetBundle::register() 方法注冊(cè)一個(gè)資源包后,就使它的資源可被 Web 訪問(wèn)了,注冊(cè)了資源包的頁(yè)面會(huì)自動(dòng)包含和引用資源包內(nèi)指定的 JS 和 CSS 文件。
更多細(xì)節(jié)請(qǐng)參閱?前端資源管理(Asset)?章節(jié)。
Yii 2.0 很多常用的靜態(tài)助手類,包括:
請(qǐng)參考助手一覽?章節(jié)來(lái)了解更多。
Yii 2.0 引進(jìn)了表單欄(field)的概念,用來(lái)創(chuàng)建一個(gè)基于 yii\widgets\ActiveForm 的表單。一個(gè)表單欄是一個(gè)由標(biāo)簽、輸入框、錯(cuò)誤消息(可能還有提示文字)組成的容器,被表示為一個(gè) yii\widgets\ActiveField 對(duì)象。使用表單欄建立表單的過(guò)程比以前更整潔利落:
<?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(); ?>
請(qǐng)參考創(chuàng)建表單章節(jié)來(lái)了解更多細(xì)節(jié)。
Yii 1.1 中,查詢語(yǔ)句的生成分散在多個(gè)類中,包括?CDbCommand
,CDbCriteria
?以及?CDbCommandBuilder
。Yii 2.0 以 yii\db\Query 對(duì)象的形式表示一個(gè)數(shù)據(jù)庫(kù)查詢,這個(gè)對(duì)象使用 yii\db\QueryBuilder 在幕后生成 SQL 語(yǔ)句。例如:
$query = new \yii\db\Query();
$query->select('id, name')
->from('user')
->limit(10);
$command = $query->createCommand();
$sql = $command->sql;
$rows = $command->queryAll();
最重要的是,這些查詢生成方法還可以和活動(dòng)記錄配合使用。
請(qǐng)參考查詢生成器(Query Builder)章節(jié)了解更多內(nèi)容。
Yii 2.0 的活動(dòng)記錄改動(dòng)了很多。兩個(gè)最顯而易見(jiàn)的改動(dòng)分別涉及查詢語(yǔ)句的生成(query building)和關(guān)聯(lián)查詢的處理(relational query handling)。
1.1 中的?CDbCriteria
?類在 Yii 2 中被 yii\db\ActiveQuery 所替代。這個(gè)類是繼承自 yii\db\Query,因此也繼承了所有查詢生成方法。開(kāi)始拼裝一個(gè)查詢可以調(diào)用 yii\db\ActiveRecord::find() 方法進(jìn)行:
// 檢索所有“活動(dòng)的”客戶和訂單,并以 ID 排序:
$customers = Customer::find()
->where(['status' => $active])
->orderBy('id')
->all();
要聲明一個(gè)關(guān)聯(lián)關(guān)系,只需簡(jiǎn)單地定義一個(gè) getter 方法來(lái)返回一個(gè) yii\db\ActiveQuery 對(duì)象。getter 方法定義的屬性名代表關(guān)聯(lián)表名稱。如,以下代碼聲明了一個(gè)名為?orders
?的關(guān)系(1.1 中必須在?relations()
?方法內(nèi)聲明關(guān)系):
class Customer extends \yii\db\ActiveRecord
{
public function getOrders()
{
return $this->hasMany('Order', ['customer_id' => 'id']);
}
}
現(xiàn)在你就可以通過(guò)調(diào)用?$customer->orders
?來(lái)訪問(wèn)關(guān)聯(lián)表中某用戶的訂單了。你還可以用以下代碼進(jìn)行一場(chǎng)指定條件的實(shí)時(shí)關(guān)聯(lián)查詢:
$orders = $customer->getOrders()->andWhere('status=1')->all();
當(dāng)貪婪加載一段關(guān)聯(lián)關(guān)系時(shí),Yii 2.0 和 1.1 的運(yùn)作機(jī)理并不相同。具體來(lái)說(shuō),在 1.1 中使用一條 JOIN 語(yǔ)句同時(shí)查詢主表和關(guān)聯(lián)表記錄。在 Yii 2.0 中會(huì)使用兩個(gè)沒(méi)有 JOIN 的 SQL 語(yǔ)句:第一條語(yǔ)句取回主表記錄,第二條通過(guò)主表記錄經(jīng)主鍵篩選后查詢關(guān)聯(lián)表記錄。
當(dāng)生成返回大量記錄的查詢時(shí),可以鏈?zhǔn)綍?shū)寫(xiě) yii\db\ActiveQuery::asArray() 方法,這樣會(huì)以數(shù)組的形式返回查詢結(jié)果,而不必返回 yii\db\ActiveRecord 對(duì)象,這能顯著降低因大量記錄讀取所消耗的 CPU 時(shí)間和內(nèi)存。如:
$customers = Customer::find()->asArray()->all();
另一個(gè)改變是你不能再通過(guò)公共變量定義屬性(Attribute)的默認(rèn)值了。如果你需要這么做的話,可以在你的記錄類的?init
?方法中設(shè)置它們。
public function init()
{
parent::init();
$this->status = self::STATUS_NEW;
}
曾幾何時(shí),在 1.1 中重寫(xiě)一個(gè)活動(dòng)記錄類的構(gòu)造方法會(huì)導(dǎo)致一些問(wèn)題。它們不會(huì)在 2.0 中出現(xiàn)了。需要注意的是,如果你需要在構(gòu)造方法中添加一些參數(shù),恐怕必須重寫(xiě) yii\db\ActiveRecord::instantiate() 方法。
活動(dòng)記錄方面還有很多其他的變化與改進(jìn),請(qǐng)參考活動(dòng)記錄章節(jié)以了解更多細(xì)節(jié)。
在 2.0 中遺棄了活動(dòng)記錄行為基類?CActiveRecordBehavior
。如果你想創(chuàng)建活動(dòng)記錄行為,需要直接繼承?yii\base\Behavior
。如果行為類中需要表示一些事件,需要像這樣覆寫(xiě)?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)
{
// ...
}
}
1.1 中的?CWebUser
?類現(xiàn)在被 yii\web\User 所取代,隨之?CUserIdentity
?類也不在了。與之相對(duì)的,為達(dá)到相同目的,你可以實(shí)現(xiàn) yii\web\IdentityInterface 接口,它使用起來(lái)更直觀。在高級(jí)應(yīng)用模版里提供了一個(gè)這樣的一個(gè)例子。
要了解更多細(xì)節(jié)請(qǐng)參考認(rèn)證(Authentication),授權(quán)(Authorization)以及高級(jí)應(yīng)用模版?這三個(gè)章節(jié)。
Yii 2.0 的 URL 管理跟 1.1 中很像。一個(gè)主要的改進(jìn)是現(xiàn)在的 URL 管理支持可選參數(shù)了。比如,如果你在 2.0 中定義了一個(gè)下面這樣的規(guī)則,那么它可以同時(shí)匹配?post/popular
?和?post/1/popular
?兩種 URL。而在 1.1 中為達(dá)成相同效果,必須要使用兩條規(guī)則。
[
'pattern' => 'post/<page:\d+>/<tag>',
'route' => 'post/index',
'defaults' => ['page' => 1],
]
請(qǐng)參考URL 解析和生成?章節(jié),以了解更多細(xì)節(jié)。.