您的位置:首页 > 编程语言 > PHP开发

Yii自学笔记(一)

2016-05-23 15:26 267 查看
注:个人用于自学回顾用,勿喷。

yii-MVC整个请求流程

1.用户发出了访问 URL http://localhost/yii1/yyi1first/index.php?r=user/index&id=2 的请求, Web 服务器通过执行入口脚本 index.php 处理此请求。

2.入口脚本创建了一个 应用 实例并执行。

3.应用从一个叫做 request 的 应用组件 中获得了用户请求的详细信息。

4.应用在一个名叫 urlManager 的应用组件的帮助下,决定请求的 控制器 和 动作 。在这个例子中,控制器是 user,它代表 UserController 类; 动作是 index ,其实际含义由控制器决定。

5.应用创建了一个所请求控制器的实例以进一步处理用户请求。控制器决定了动作 index 指向控制器类中的一个名为 actionIndex 的方法。然后它创建并持行了与动作关联的过滤器(例如访问控制,基准测试)。 如果过滤器允许,动作将被执行。

6.动作从数据库中读取一个 ID 为 1 的 User 模型。

7.动作通过 User 模型渲染一个名为 index 的 视图。

8.视图读取并显示 User 模型的属性。

9.视图执行一些 小物件。

10.视图的渲染结果被插入一个 布局。

11.动作完成视图渲染并将其呈现给用户。

入口文件理解

设置测试模式,引入YII框架,并且根据指定的配置(main.php)创建一个web实例并且执行。

其实就是实例CWebApplication对象

应用(前端控制器)main.php

应用配置

array(

‘name’=>’Yii Framework’,

‘defaultController’=>’site’,

)

可通过web实例访问name

Yii::app()->name;

应用基础目录
1.指包含了所有安全敏感的PHP脚本和数据的根目录。
2.默认状态下,它是一个位于含有入口脚本目录的名为 protected 的子目录。
3.它可以通过设置config/main中的 basePath 属性自定义
4.作用是为了防止被客户直接访问。
5.Apache可以通过.htaccess文件实现该目的

应用组件
要访问一个应用组件,使用 Yii::app()->ComponentID ,其中的 ComponentID 是指组件的ID(例如 Yii::app()->cache)。
注:应用组件如果未被访问默认是未创建的,如果无论是否访问都要创建则需要将其ID列在应用的preload属性中。
如:main中的'preload'=>array('log').  (*这个如何实现需要关注下)

核心应用组件
这个需要查看CWebApplication预定义的组件
先关心几个组件
CLogRouter  未访问就创建
CHttpRequest
CUrlManager
CHttpSession
CWebUser
后期会跟踪原代码

*应用的生命周期(这个需要重点查看)
当处理用户请求时,应用将经历如下声明周期:
1.通过 CApplication::preinit() 预初始化应用;
2.设置类的自动装载器和错误处理;
3.注册核心类组件;
4.加载应用配置;
5.通过 CApplication::init() 初始化应用:
注册应用行为;
载入静态应用组件;(预计跟前端差不多)
6.触发 onBeginRequest 事件;
7.处理用户请求:
解析用户请求;
创建控制器;  (访问时候创建*)
运行控制器;
8触发 onEndRequest 事件。


控制器

CController或者子类的对象,动作最简单形式就是action开头的控制器方法

路由:控制器和动作以 ID 识别
如:控制器ID'path/to/xyz'对应的控制器类文件 protected/controllers/path/to/XyzController.php;
动作ID:如果控制器中有actionEdit方法,动作ID就是edit
路由 post/edit 代表 PostController 及其 edit 动作,请求方式http://hostname/index.php?r=post/edit
注:路由默认是大小写敏感,可通过CUrlManager::caseSensitive 为 false 使大小写不敏感。

控制器实例化
在CWebApplication处理到来的请求时创建。
三种确定控制器的类以及类文件位置
1.指定CWebApplication::catchAllRequest,控制器将给予此属性创建,而用户指定的被忽略.这个常用于维护系统时候使用。
2. CWebApplication::controllerMap中找到了 ID, 相应的控制器配置将被用于创建控制器实例;
3.上面所说的路由;

动作
除了上面说的通过动作ID访问,还可以通过继承CAction实现动作类如下
class UpdateAction extends CAction
{
public function run()
{
// place the action logic here
}
}
再在控制类中覆盖实现actions()方法,引入动作类,如下
class PostController extends CController
{
public function actions()
{
return array(
'edit'=>'application.controllers.post.UpdateAction',
);
}
}

动作参数绑定
1.动作类的参数必须和$_GET传入的参数名字一直,如果参数未定义并且没有默认值则会被 CHttpException (错误代码 400) 捕获异常。
注:这个是否存在风险?
2.如果声明了参数类型array,如果传入的还是字符串格式,则会被强制转换成数组。

过滤器
1.过滤器可在控制器之前或者之后执行校验,一个动作可以有多个过滤器。
2.过滤器可以定义控制器类方法,方法名称必须filter开头;
如filterAccessControl 定义了accessControl的过滤器。
3.过滤器可以阻止动作以及后面其他过滤器的执行。
4.过滤器方法格式如下:
1).方法参数必须是 CFilterChain 的实例
public function filterAccessControl($filterChain)
{

//filterChain->run(); 这个方法为了继续执行过滤器和动作  *
}

2).过滤器实现或者继承CFilter的实体
class PerformanceFilter extends CFilter
{
protected function preFilter($filterChain)
{
// 动作被执行之前应用的逻辑
return true; // 如果动作不应被执行,此处返回 false
}

protected function postFilter($filterChain)
{
// 动作执行之后应用的逻辑
}
}

5.实现动作应用过滤器需要覆盖CController::filters() 方法:
class PostController extends CController
{
public function filters()
{
return array(
'postOnly + edit, create',
array(
'application.filters.PerformanceFilter - edit, create',
'unit'=>'second',
),
);
}
}

*上面指定了两个过滤器: postOnly 和 PerformanceFilter。
postOnly 过滤器是基于方法(在CController中定义过了)
PerformanceFilter基于对象,指定的过滤器文件protected/filters/PerformanceFilter,使用数组并且属性unit可以被初始化。
‘+’说明只过滤edit,create方法,‘-’说明除了edit,create其他都过滤,如果不定义就是所有方法都校验。


模型

模式是CModel或其子类的实例

YII实现两种模型:表单模型和 Active Record,都继承相同的CModel;

表单模型是 CFormModel 的实例,单模型用于保持从用户的输入获取的数据。 这些数据经常被获取,使用,然后丢弃。

Active Record是CActiveRecord 或其子类的实例,代表数据表中的一行(这个有点疑问,为什么不是表对象)

视图

视图逻辑和界面最好分开,逻辑放于控制器或者模型中。

视图的名称和视图脚本名称是一样的。CController::render()是渲染时候调用,会在protected/views/ControllerID目录下寻找视图

视图脚本名称(views下面的文件)可以通过this访问控制器实例(这个是对应的控制器),通过this->propertyName方法拉取控制器任何属性(包括私有属性么?)。

如:this−>render(‘edit′,array(‘var1′=>value1,

‘var2’=>value2,));这样渲染给edit.php这个视图脚本,在这个脚本中可以直接访问var1和$var2。

1.布局
通常包含视图通用部分,比如头尾部分,然后可以把内容嵌入其中。
......header here......
<?php echo $content; ?>
......footer here......
$content这个是存储被渲染的视图结果。

使用render()方法默认使用布局。默认的布局文件是protected/views/layouts/main.php。
可以通过CController::layout和CWebApplication::layout方法改变默认布局文件
使用renderPartial()则不带布局的视图。

2.小物件
使用方式
<?php $this->beginWidget('path.to.WidgetClass'); ?>
...可能会由小物件获取的内容主体...
<?php $this->endWidget(); ?>
或者

<?php $this->widget('path.to.WidgetClass'); ?>
后者用于不需要任何 body 内容的组件.

小物件可通过配置来定制它的表现.这是通过调用 CBaseController::beginWidget 或 CBaseController::widget 设置其初始化属性值来完成的。
<?php
$this->widget('CMaskedTextField',array(
'mask'=>'99/99/9999'
));
?>
可以初始化小物件类。

创建一个新的小物件
继承 CWidget 并覆盖其init() 和 run() 方法,
class MyWidget extends CWidget
{
public function init()
{
// 此方法会被 CController::beginWidget() 调用
}

public function run()
{
// 此方法会被 CController::endWidget() 调用
}
}

小物件可以自己拥有视图。视图位置位于包含小物件类文件目录的views子目录下。可以通过CWidget::render()渲染,但是没有布局文件支持。小物件视图中的$this指向小物件实例。

3.系统视图
通常用于张氏YII错误和日志信息
命名规则:errorXXX:
如果CHttpException跑出404错误,那么error404会显示出来。
系统默认在protected/views/system下创建同名视图文件进行自定义


组件 (目前组件在开发中不是很重要,后期再深入学习)

组件是 CComponent 或其子类的实例。可通过CComponent查看

模块(很重要)

模块是单独的软件单位,包含模型,视图,控制器以及其他组件;

不能单独部署,必须存在于应用中。

通用的模块有利于复用。

1.创建模块
模块的目录名称即模块的唯一ID,例如:
forum/    //模块ID
ForumModule.php            模块类文件
components/                包含可复用的用户组件
views/                  包含小物件的视图文件
controllers/               包含控制器类文件
DefaultController.php   默认的控制器类文件
extensions/                包含第三方扩展
models/                    包含模块类文件
views/                     包含控制器视图和布局文件
layouts/                包含布局文件
default/                包含 DefaultController 的视图文件
index.php            首页视图文件

模块必须有一个继承自 CWebModule 的模块类;
类的名字通过表达式 ucfirst($id).'Module' 确定,其中的 $id 代表模块的 ID (或者说模块的目录名字),如上面的ForumModule.php;
模块类是存储模块代码间可共享信息的中心位置。例如,我们可以使用 CWebModule::params 存储模块参数,使用 CWebModule::components 分享模块级的 应用组件 .

2.使用模块
要使用模块,首先将模块目录放在 应用基础目录 的 modules 中;
在应用的 modules 属性中声明模块 ID ;
如:
return array(
......
'modules'=>array('forum',...),
......
);

模块也可以设置初始属性值
return array(
......
'modules'=>array(
'forum'=>array(
'postPerPage'=>20,
),
),
......
);

可以通过直接访问模块属性值
$postPerPage=Yii::app()->controller->module->postPerPage;

*模块中的控制器动作可以通过 路由 moduleID/controllerID/actionID 访问
比如上面的DefaultController控制器,可以通过forum/default/create访问动作,
URL对应的如:http://xxx/index.php?r=forum/default/create.

3.嵌套模块
模块可以无限极嵌套;
一个模块包含另一个模块,前者为父模块,后者为子模块;
子模块必须定义在父模块的modules属性中;
访问子模块中的控制器动作
parentModuleID/childModuleID/controllerID/actionID。


*路径别名与名字空间

1.Yii预定义了一下几个别名

1).system: 表示 Yii 框架目录;

2).zii: 表示 Zii 库 目录;

3).application: 表示应用的 基础目录;

4).webroot: 表示 入口脚本 文件所在的目录。

5).ext: 表示包含了所有第三方 扩展 的目录。

如果定义了模块,模块ID定义了根别名,指向相依的模块根目录,如上面定义的模块forum

可以通过YiiBase::getPathOfAlias()把别名翻译为其相对应的路径。
如system.web.CController 会被翻译为 yii/framework/web/CController;

2.引导类(importing Classes)
Yii::import('system.web.CController');
导入的类只有它第一次被引用才会被包含进来;
YII框架定义的类已经提前被导入。

预先导入机制
使用Class Map这个类,YII内置类也是使用这个方法。
如:
Yii::$classMap=array(
'ClassName1' => 'path/to/ClassName1.php',
'ClassName2' => 'path/to/ClassName2.php',
......
);
必须在CWebApplication::run()执行前执,这样在YII应用中无需显式导入或者包含文件就可以使用。

3.导入整个目录
Yii::import('system.web.*');

4.命名空间(Namespace)(这个文档材料有点少)
命名空间是指对一些类名的一个逻辑组合。
路径别名用于指向一个类文件或者目录。
命名空间和路径别名不冲突。

使用命名空间
比如说,类application\components\GoogleMap 在命名空间application\components下的类。
若自动导入使用命名空间的类,命名空间的格式必须和路径别名相似
比如说,类application\components\GoogleMap 所对应的路径必须和别名application.components.GoogleMap一致。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  yii web