yii2框架官方說明文檔 http://www.yiiframework.com/doc/guide/2.0/zh_cn/caching.pagejavascript
yii2建立您的第一個application應用 http://www.yiiframework.com/doc/guide/2.0/zh_cn/quickstart.first-appphp
一個Web請求在Yii內部的執行流程以下圖所示:html
組件名前端 |
角色與責任java |
index.phpnode |
入口腳本。建立Application的單例對象。mysql |
applicationgit |
前端控制器。分析用戶請求並將其分派到合適的控制器中以做進一步處理。它同時做爲服務中心,維護應用級別的配置。github |
requestredis |
解析用戶的請求。 |
urlManager |
幫助application決定請求的控制器和動做。 |
controller |
執行所請求的動做,動做一般會引入所必要的模型並渲染相應的視圖,動做完成視圖渲染並將其呈現給用戶。 |
model |
讀取數據庫或進行其餘業務操做。 |
view |
視圖渲染出最終的頁面。 |
假設有這樣一個包含幾個子應用的Web應用,例如:
Ø Front-end:面向外部用戶的Web站點
Ø Back-end:爲管理員提供管理功能的Web站點
Ø Console:在終端中做爲定時做業執行
Ø Web API:爲第三方提供集成的API
Ø 包含表明特定數據的屬性
Ø 包含業務邏輯、驗證規則
Ø 包含操縱數據的代碼
Ø 不該使用$_GET,$_POST等與界面類型綁定的變量
Ø 避免嵌入HTML等展現層代碼
有時聽從第三條「包含操縱數據的代碼」會讓Model層變得很胖,所以能夠爲不一樣的子應用提供不一樣的Model子類。例如定義一個NewsBase類包含跨子應用共享的代碼,爲每一個子應用實現本身的Model類,只包含針對當前子應用的代碼。
Ø 包含展現代碼,例如HTML和簡單的遍歷、格式化、渲染PHP代碼
Ø 避免包含顯示訪問數據的代碼
Ø 避免直接訪問$_GET,$POST等變量
視圖層的代碼重用方式:
Ø 佈局:公共展現區域(如頁眉、頁腳)能夠放在一個佈局視圖中
Ø 部分視圖:非佈局代碼的代碼片斷能夠經過部分視圖重用,例如表單代碼
Ø 控件:若是部分視圖中包含大量邏輯,就能夠提取爲控件類來重用。
Ø 助手類:完成細小任務的代碼能夠用助手類來重用,例如格式化數據,產生HTML標籤
Ø 能夠訪問$_GET,$_POST等PHP變量來得到用戶請求
Ø 建立Model實例,並管理其生命週期
Ø 避免嵌入SQL語句
Ø 避免包含HTML等展現層代碼
在設計良好的MVC應用程序中,控制器經過很是瘦,只包含幾十行代碼。然而模型層一般會很胖,由於它包含了不一樣領域的業務邏輯,知足特定的需求。
Yii 預約義了一系列核心應用組件,提供常見Web 應用中所用的功能。像【1.1組件角色】中的urlManager,【3數據訪問】中將用到的CDbConnection,以及對Memcached支持等等都是經過可擴展的應用組件的形式加入到Yii中的。
下面咱們列出了由 CWebApplication 預約義的核心組件。
· assetManager: CAssetManager -管理私有資源文件的發佈。
· authManager: CAuthManager -管理基於角色的訪問控制(RBAC).
· cache: CCache -提供數據緩存功能。注意,你必須指定實際的類(例如CMemCache, CDbCache)。不然,當你訪問此組件時將返回 NULL。
· clientScript: CClientScript -管理客戶端腳本(javascripts 和CSS).
· coreMessages: CPhpMessageSource -提供 Yii 框架用到的核心信息的翻譯。
· db: CDbConnection -提供數據庫鏈接。注意,使用此組件你必須配置其 connectionString 屬性。
· errorHandler: CErrorHandler -處理未捕獲的 PHP 錯誤和異常。
· format: CFormatter -格式化數值顯示。此功能從版本1.1.0 起開始提供。
· messages: CPhpMessageSource -提供Yii應用中使用的信息翻譯。
· request: CHttpRequest -提供關於用戶請求的信息。
· securityManager: CSecurityManager -提供安全相關的服務,例如散列,加密。
· session: CHttpSession -提供session相關的功能。
· statePersister: CStatePersister -提供全局狀態持久方法。
· urlManager: CUrlManager -提供 URL 解析和建立相關功能
· user: CWebUser -提供當前用戶的識別信息。
· themeManager: CThemeManager -管理主題。
要激活應用組件,咱們須要定製Application。方式一是提供一個配置文件以建立Application實例時初始化其屬性值;另外一種方式是繼承CWebApplication。
咱們一般採用方式一,在一個單獨的PHP腳本(例如protected/config/main.php)中保存這些配置。要激活某個應用組件,咱們須要在這個PHP腳本中配置Application的components屬性。例以下面激活memcached組件實現緩存功能:
array(
......
'components'=>array(
......
'cache'=>array(
'class'=>'CMemCache',
'servers'=>array(
array('host'=>'server1', 'port'=>11211, 'weight'=>60),
array('host'=>'server2', 'port'=>11211, 'weight'=>40),
),
),
),
)
而後在入口腳本index.php中,將配置文件的名字做爲參數傳遞給應用構造器:
$app=Yii::createWebApplication($configFile);
如今就能夠訪問應用組件了。使用Yii::app()->ComponentID,其中的ComponentID是指組件的ID(例如Yii::app()->cache)。
Yii數據訪問創建在PHP的PDO擴展上,經過一個統一的接口訪問不一樣的數據庫。在此基礎上,Yii提供了三種數據庫編程方式。
Yii DAO 主要包含以下四個類:
CDbConnection:表明一個數據庫鏈接。
CDbCommand:表明一條經過數據庫執行的SQL 語句。
CDbDataReader:表明一個只向前移動的,來自一個查詢結果集中的行的流。
CDbTransaction:表明一個數據庫事務。
使用方法與Java的JDBC很像,例如:
$connection=Yii::app()->db;
$command=$connection->createCommand($sql);
// 查詢
$dataReader=$command->query();
while(($row=$dataReader->read())!==false){ ... }
// 綁定參數
$sql="INSERT INTO tbl_user (username, email) VALUES(:username,:email)";
$command=$connection->createCommand($sql);
// 用實際的用戶名替換佔位符 ":username"
$command->bindParam(":username",$username,PDO::PARAM_STR);
// 用實際的 Email 替換佔位符 ":email"
$command->bindParam(":email",$email,PDO::PARAM_STR);
$command->execute();
Yii的查詢構造器(Query Builder)提供了面向對象方式編寫SQL語句。例如:
$user = Yii::app()->db->createCommand()
->select('id, username, profile')
->from('tbl_user u')
->join('tbl_profile p', 'u.id=p.user_id')
->where('id=:id', array(':id'=>$id))
->queryRow();
對於比較簡單的SQL語句來講,使用這種方式編程的優勢有:
Ø 提升代碼可讀性
Ø 參數綁定避免SQL注入攻擊
Ø 在PDO基礎上的進一步數據庫抽象,簡化數據遷移
雖然前兩種方式已經能夠處理幾乎任何數據庫相關的任務,但極可能咱們會花費90%的時間以編寫一些執行普通CRUD操做的SQL語句。並且咱們代碼中混雜的SQL語句也會使代碼變得難以維護。要解決這些問題,咱們可使用活動對象模式(Active Record,簡稱AR)。
AR是一個流行的對象-關係映射(ORM)技術。每一個AR類表明一個數據表,數據表的列在 AR 類中體現爲類的屬性,一個AR實例則表示表中的一行。常見的CRUD操做做爲AR的方法實現。所以,咱們能夠以一種更加面向對象的方式訪問數據。
classPostextendsCActiveRecord
{
publicstaticfunctionmodel($className=__CLASS__)
{
returnparent::model($className);
}
publicfunctiontableName()
{
return'tbl_post';
}
}
$post=newPost;
$post->title='sample post';
$post->content='post body content';
$post->save();
具體例子見【6.2模型層實例】。
Yii 提供了不一樣的緩存組件,能夠將緩存數據存儲到不一樣的媒介中。例如, CMemCache 組件封裝了 PHP 的 memcache 擴展並使用內存做爲緩存存儲媒介。 CApcCache 組件封裝了 PHP APC 擴展; 而 CDbCache 組件會將緩存的數據存入數據庫。下面是一個可用緩存組件的列表:
· CMemCache:使用 PHP memcache 擴展.
· CXCache:使用 PHP XCache 擴展。注意,這個是從 1.0.1 版本開始支持的。
· CEAcceleratorCache:使用 PHP EAccelerator 擴展.
· CDbCache:使用一個數據表存儲緩存數據。默認狀況下,它將建立並使用在runtime 目錄下的一個SQLite3 數據庫。你也能夠經過設置其 connectionID 屬性指定一個給它使用的數據庫。
· CZendDataCache:使用 ZendData Cache 做爲後臺緩存媒介。注意,這個是從1.0.4 版本開始支持的。
· CFileCache:使用文件存儲緩存數據。這個特別適合用於存儲大塊數據(例如頁面)。注意,這個是從1.0.6 版本開始支持的。
· CDummyCache:目前 dummy 緩存並不實現緩存功能。此組件的目的是用於簡化那些須要檢查緩存可用性的代碼。例如,在開發階段或者服務器還沒有支持實際的緩存功能,咱們可使用此緩存組件。當啓用了實際的緩存支持後,咱們能夠切換到使用相應的緩存組件。在這兩種狀況中,咱們可使用一樣的代碼Yii::app()->cache->get($key)
獲取數據片斷而不須要擔憂 Yii::app()->cache
可能會是 null
。此組件從 1.0.5 版開始支持。
(TODO 介紹Yii和Gii,能夠用來快速開發系統原型)
(TODO 介紹基於PHPUnit的單元測試)
在《Yii入門實例.docx》的基礎上增長下面三個實例。
演示程序的總體目錄結構以下:
app/
|-- index.php
`-- protected
|-- config
| `-- main.php
|-- controllers
| |-- CacheController.php
| |-- HelloController.php
| |-- PostController.php
| |-- route
| | |-- CreateAction.php
| | |-- DeleteAction.php
| | `-- UpdateAction.php
| `-- RouteController.php
|-- extensions
| `-- redis
| |-- CRedisCache_old.php
| |-- CRedisCache.php
| `-- Predis.php
|-- filters
| `-- PerfFilter.php
|-- models
| `-- Post.php
`-- views
|-- cache
| `-- result.php
|-- hello
| `-- result.php
|-- post
| `-- result.php
`-- route
`-- result.php
此控制器層實例主要演示三方面:
Ø 請求參數自動綁定到方法形參
Ø 獨立的Action類替代action方法
Ø 使用過濾器實現關注點分離
1.helloyii/app/protected/controllers/RouteController.php
===============================================================================
classRouteController extends CController
{
publicfunction actions()
{
$path= 'application.controllers.route.';
returnarray(
'create'=>$path.'CreateAction',
'update'=>$path.'UpdateAction',
'delete'=>$path.'DeleteAction',
);
}
publicfunction filters()
{
returnarray(
array('application.filters.PerfFilter'),
);
}
}
2.helloyii/app/protected/controllers/route/DeleteAction.php
===============================================================================
class DeleteAction extends CAction //2.獨立的Action類
{
public function run($id) //1.$_GET請求中的參數自動綁定到方法形參
{
$data = "This isDeleteAction served you, id:$id";
Yii::app()->getController()->render('result',array('data'=>$data));
}
}
如今訪問http://helloyii.com/app/index.php?r=route/delete&id=1就能看到效果。
注:CreateAction.php和UpdateAction.php的代碼與之相似,就不列舉了。
3.helloyii/app/protected/filters/PerfFilter.php
===============================================================================
classPerfFilter extends CFilter //3.實現過濾器抽象類,對Action進行先後處理
{
protectedfunction preFilter($filterChain)
{
echo'PerfFilter pre action<br/>';
returntrue;
}
protectedfunction postFilter($filterChain)
{
echo'<br/>PerFilter post action';
returntrue;
}
}
4.helloyii/app/protected/views/route/result.php
===============================================================================
<?php
echo$data;
?>
首先建立數據庫helloyii,在其中建立一張新表用來演示。
CREATETABLEtbl_post(
idINTEGERNOTNULLPRIMARYKEYAUTO_INCREMENT,
titleVARCHAR(128)NOTNULL,
contentTEXTNOTNULL,
create_timeINTEGERNOTNULL
);
1.helloyii/app/protected/config/main.php
===============================================================================
return array(
'components' => array(
'db' => array(
'connectionString' =>'mysql:host=localhost;port=3306;dbname=helloyii;',
'emulatePrepare' => true,
'username'=> 'root',
'password'=> '',
'charset' =>'utf8',
),
),
'import'=>array(
'application.models.*',
),
);
注意:使用main.php對應用進行配置的話,要修改入口腳本index.php:
$config=dirname(__FILE__).'/protected/config/main.php';
Yii::createWebApplication($config)->run();
2.helloyii/app/protected/controllers/RouteController.php
===============================================================================
class PostController extends CController
{
public function actionQuery()
{
// Insert one row totable
$post = new Post;
$post->title ='sample post';
$post->content ='content for sample post';
$post->create_time =time();
$post->save();
// Query all rows intable
$data =Post::model()->findAll();
//Delegate viewer torender
Yii::app()->getController()->render('result',array('data'=>$data));
}
}
3.helloyii/app/protected/models/Post.php
===============================================================================
class Post extends CActiveRecord
{
public static functionmodel($className=__CLASS__)
{
returnparent::model($className);
}
public function tableName()
{
return 'tbl_post'; //對應數據庫中的表名
}
}
4.helloyii/app/protected/views/post/result.php
===============================================================================
<html>
<head></head>
<body>
<table border="1">
<tr>
<th>ID</th>
<th>Title</th>
<th>Content</th>
<th>CreateTime</th>
</tr>
<?php
foreach ($data as $row)
{
echo "<tr>";
echo"<td>".$row->id."</td>";
echo"<td>".$row->title."</td>";
echo"<td>".$row->content."</td>";
echo"<td>".$row->create_time."</td>";
echo "</tr>";
}
?>
</table>
</body>
</html>
如今訪問http://helloyii.com/app/index.php?r=post/query,效果以下圖:
詳見《Yii集成Redis》。
1 Yii的控制器官方介紹
http://www.yiiframework.com/doc/guide/1.1/zh_cn/basics.controller
2 MVC最佳實踐官方介紹
http://www.yiiframework.com/doc/guide/1.1/zh_cn/basics.best-practices
切換至/usr/local/src下,下載並安裝redis:
$ wgethttp://redis.googlecode.com/files/redis-2.6.12.tar.gz
$ tar xzf redis-2.6.12.tar.gz
$ cd redis-2.6.12
$ make
進入redis-2.6.12目錄,修改redis.conf:
daemonize yes
啓動服務端:
$src/redis-server redis.conf
進入命令行驗證服務是否啓動:
$src/redis-cli
redis> set foo bar
OK
redis> get foo
"bar"
目前主要有兩種Yii插件:
Ø Rediscache:基於predis(Redis的純PHP實現客戶端),無需安裝Redis for PHP擴展。
Ø YiiRedis:基於phpredis客戶端,須要安裝Redis for PHP擴展。
這裏採用Rediscache插件,避免線上安裝Redis for PHP擴展。
從如下地址下載Rediscache插件:
http://www.yiiframework.com/extension/rediscache/files/redis.zip
將插件解壓到helloyii/app/protected/extensions中:
插件文件部署後的位置應爲:helloyii/app/protected/extensions/redis/CredisCache.php
1.helloyii/app/protected/config/main.php
===============================================================================
return array(
'components' => array(
…
'cache'=>array(
'class'=>'ext.redis.CRedisCache', //對應protected/extensions/redis/CredisCache.php
'servers'=>array(
array(
'host'=>'127.0.0.1',
'port'=>6379,
),
),
),
),
…
);
從GitHub上下載插件https://github.com/lincsanders/PRedisCacheHttpSession
解壓到helloyii/app/protected/extensions下:
插件文件部署後的位置應爲:
helloyii/app/protected/extensions/PredisCacheHttpSession/PRedisCacheHttpSession.php
'session'=>array(
'class' =>'ext.PRedisCacheHttpSession.PRedisCacheHttpSession',
'database' => 9,
),
注意:緩存和會話的database屬性必定要區分開,用不一樣的Redis數據庫來保存。
編寫一個讀寫緩存的控制器進行測試。
2.helloyii/app/protected/controllers/CacheController.php
===============================================================================
class CacheController extends CController
{
public function actionFetch($key, $value)
{
Yii::app()->cache->set($key, $value);
$data = Yii::app()->cache->get($key);
Yii::app()->getController()->render('result',array('data'=>$data));
}
}
3.helloyii/app/protected/views/cache/result.php
===============================================================================
<?php
echo$data;
?>
如今訪問:http://helloyii.com/app/index.php?r=cache/fetch&key=a&value=b
而後經過redis-cli命令行客戶端查看下緩存的變化:
能夠經過redis-cli客戶端查看緩存:
$ src/redis-cli
redis> keys ‘*’
…
1官方安裝手冊
2 Yii的Redis插件1:rediscache
http://www.yiiframework.com/extension/rediscache/
3 Yii的Redis插件2:yiiredis
https://github.com/phpnode/YiiRedis
4 Yii CCache接口的API
http://www.yiichina.com/api/CCache#get-detail
5 Redis在YiiFramework中的使用
http://denghai260.blog.163.com/blog/static/726864092012323101628773/