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/