yii中在init方法里面如何yii2 判断手机访问是手机端还是pc端访问,如果是手机端访问,显示手机端的域名地址

手机网站的提示框除了alert有特别的代码吗?_问答_ThinkSAAS
手机网站的提示框除了alert有特别的代码吗?
手机网站的提示框除了alert有特别的代码吗?
手机网站的提示框除了alert有特别的代码吗?浏览很多手机站弹出提示框都是黑色透明很漂亮,直接使用alert没这个效果。能推荐一个基于jquery的控件吗
PS: 抱歉,忘了说环境了,我使用的是Bootstrap3,它自带的弹出效果不是太好,所以想找个轻量的替代品。
新出来个,尝试下
给你一个TAOBAO的,我用的是zepto,应该和jQuery兼容
function compareVersion(v1, v2) {
v1 = v1.toString().split(".");
v2 = v2.toString().split(".");
for (var i = 0; i & v1.length || i & v2. i++) {
var n1 = parseInt(v1[i], 10),
n2 = parseInt(v2[i], 10);
if (window.isNaN(n1)) {
if (window.isNaN(n2)) {
if (n1 & n2) {
if (n1 & n2) {
function callback(func, result) {
var ua = navigator.userAgent,
isAndroid = (/Android/i).test(ua),
osVersion = ua.match(/(?:OS|Android)[/s](d+[._]d+(?:[._]d+)?)/i)
if (isAndroid && compareVersion(osVersion,"2.4.0") & 0) {
setTimeout(function() {
func && func(result)
func && func(result)
(function(e) {
if (void 0 == window.define) {
var d = {},
h = d.exports = {};
e(null, h, d);
window.floatNotify = window.notification = d.exports
} else define(e)
})(function(require, exports, module) {
function e(a) {
this._options = d.extend({
mode:"msg",
text:"u7f51uu793a",
useTap: !1
}, a || {});
this._init()
var d = $,
h = d(window),
&div class="c-float-popWrap msgMode hide"&&div class="c-float-modePop"&&div class="warnMsg"&&/div&&div class="content"&&/div&&div class="doBtn"&&button class="ok"&u786eu5b9a&/button&&button class="cancel"&u53d6u6d88&/button&&/div&&/div&&/div&
m = c.find(".warnMsg"),
n = c.find(".content"),
o = c.find(".doBtn .ok"),
p = c.find(".doBtn .cancel"),
d.extend(e.prototype, {
_init: function() {
var a = this,
b = a._options,
g = b.mode,
k = b.text,
e = b.content,
f = b.callback,
l = b.background,
t = b.btns,
b = b.useTap ?"tap":"click",
i = c.attr("class"),
i = i.replace(/(msg|alert|confirm)Mode/i, g +"Mode");
c.attr("class", i);
l && c.css("background", l);
k && m.html(k);
e && n.html(e);
t && o.html(t[0]);
t && p.html(t[1]);
o.off(b).on(b, function(b) {
f.call(a, b, !0)
p.off(b).on(b, function(b) {
f.call(a, b, !1)
j || (j = !0, d("body").append(c), h.on("resize",
function() {
setTimeout(function() {
_pos: function() {
var a = document,
b = a.documentElement,
g = a.body,
this.isHide() || (a = g.scrollTop, g = g.scrollLeft, e = b.clientWidth, b = b.clientHeight, d = c.width(), f = c.height(), c.css({
top: a + (b - f) / 2,
left: g + (e - d) / 2
isShow: function() {
return c.hasClass("show")
isHide: function() {
return c.hasClass("hide")
_cbShow: function() {
var a = this._options.onS
c.css("opacity","1").addClass("show");
a && a.call(this)
show: function() {
f && (clearTimeout(f), f = void 0);
a.isShow() ? a._cbShow() : (c.css("opacity","0").removeClass("hide"), a._pos(), setTimeout(function() {
a._cbShow()
}, 300), setTimeout(function() {
c.animate({
opacity:"1"
}, 300,"linear")
_cbHide: function() {
var a = this._options.onH
c.css("opacity","0").addClass("hide");
a && a.call(this)
hide: function() {
a.isHide() ? a._cbHide() : (c.css("opacity","1").removeClass("show"), setTimeout(function() {
a._cbHide()
}, 300), setTimeout(function() {
c.animate({
opacity:"0"
}, 300,"linear")
flash: function(a) {
opt.onShow = function() {
f = setTimeout(function() {
f && b.hide()
module.exports = new function() {
this.simple = function(a, b, c) {
2 == arguments.length &&"number"== typeof arguments[1] && (c = arguments[1], b = void 0);
var d = new e({
mode:"msg",
background: b
d.flash(c || 2E3);
this.msg = function(a, b) {
return new e(d.extend({
mode:"msg",
}, b || {}))
this.alert = function(a, b, c) {
return new e(d.extend({
mode:"alert",
callback: b
}, c || {}))
this.confirm = function(a, b, c, f) {
var d = new e({
mode:"confirm",
content: b,
callback: f
this.pop = function(a) {
return new e(a)
用到了公用的样式中的
.hide{display:none}
.c-float-modePop {
text-align:
background-color: rgba(23, 23, 23, 0.9)
.c-float-modePop .warnMsg {
padding: 10px 10px 10px 10
color: #fff
.c-float-modePop .doBtn {
width: 170
margin: 0 auto
.c-float-modePop button {
padding: 6px 9px 6px 9
color: #949494;
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #404040), color-stop(100%, #2e2e2e));
border: 0;
border-radius: 2px
.c-float-shade {
width: 100%;
z-index: 99;
background-color: #000;
opacity: .5;
.c-float-shade.hide {
display: none
.c-float-popWrap {
width: 220
border-radius: 2
z-index: 9999;
overflow: hidden
.c-float-popWrap .c-float-modePop {
background-color: rgba(51, 51, 51, 0.9);
border-radius: 2
padding: 15px
.c-float-popWrap .c-float-modePop .warnMsg {
padding: 0;
font-size: 14px
.c-float-popWrap .c-float-modePop .content {
margin-top: 10px
.c-float-popWrap .c-float-modePop .doBtn {
width: 190
margin-top: 10px
.c-float-popWrap .c-float-modePop button {
height: 30
line-height: 30
color: #444;
font-size: 14
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eee), color-stop(100%, #999));
border: 0;
border-radius: 2
padding: 0;
margin: 10px 5px 0
.c-float-popWrap.hide {
-webkit-box-shadow: none
.c-float-popWrap.show {
-webkit-box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.3)
.c-float-popWrap.msgMode .c-float-modePop .content, .c-float-popWrap.msgMode .c-float-modePop .doBtn {
display: none
.c-float-popWrap.alertMode .c-float-modePop .content {
display: none
.c-float-popWrap.alertMode .c-float-modePop .doBtn .cancel {
display: none
.c-float-popWrap.confirmMode .c-float-modePop .content, .c-float-popWrap.confirmMode .c-float-modePop .doBtn {
display: block
调用方法:
1.自动消失的提示:
floatNotify.simple('提示文本','2000');
2000为可选参数,即多少毫秒自动消失
2.确认提示框:
floatNotify.confirm('提示文本','留空扩展',['确定按钮的文本','取消按钮的文本'],
function(e){
//callback 处理按钮事件
var button = $(e.target).attr('class');
if(button == 'ok'){
//按下确定按钮执行的操作
//todo ....
if(button == 'cancel') {
//按下取消按钮执行的操作
//todo ....
3.其他的可自行扩展
jQuery Mobile 自带了提示框啊,你看看文档就好啦
这个问题和手机网站、pc网站没关系,楼主想问的应该是web程序如何弹出提示框。
如果你没有使用任何移动端的web前端框架,那么需要自己手写html和js代码来手动实现弹出提示框。思路是事件触发时候,将隐藏的提示框层显示出来即可。
如果你使用了web前端框架(jquery mobile 、sencha touch等...),那么这些框架都带有可以直接调用的显示信息框的函数,查看文档直接调用即可。
添加你想要问的问题
PHP开发框架
开发工具/编程工具
服务器环境
ThinkSAAS商业授权:
ThinkSAAS为用户提供有偿个性定制开发服务
ThinkSAAS将为商业授权用户提供二次开发指导和技术支持
让ThinkSAAS更好,把建议拿来。
开发客服微信Yii2.0教程应用结构篇 - 控制器 - 教程 - Yii Framework 中文社区
Yii2.0教程应用结构篇 - 控制器
4110次浏览
控制器是 MVC 模式中的一部分, 是继承yii\base\Controller类的对象,负责处理请求和生成响应。 具体来说,控制器从应用主体接管控制后会分析请求数据并传送到模型, 传送模型结果到视图,最后生成输出响应信息。
控制器由动作组成,它是执行终端用户请求的最基础的单元,一个控制器可有一个或多个动作。
如下示例显示包含两个动作view and create 的控制器post:
namespace app\
use app\models\P
use yii\web\C
use yii\web\NotFoundHttpE
class PostController extends Controller
public function actionView($id)
$model = Post::findOne($id);
if ($model === null) {
throw new NotFoundHttpE
return $this-&render('view', [
'model' =& $model,
public function actionCreate()
$model = new P
if ($model-&load(Yii::$app-&request-&post()) && $model-&save()) {
return $this-&redirect(['view', 'id' =& $model-&id]);
return $this-&render('create', [
'model' =& $model,
在操作 view (定义为 actionView() 方法)中, 代码首先根据请求模型ID加载 模型, 如果加载成功,会渲染名称为view的视图并显示,否则会抛出一个异常。
在操作 create (定义为 actionCreate() 方法)中, 代码相似. 先将请求数据填入模型, 然后保存模型,如果两者都成功,会跳转到ID为新创建的模型的view动作,否则显示提供用户输入的create视图。
终端用户通过所谓的路由寻找到操作,路由是包含以下部分的字符串:
模型ID: 仅存在于控制器属于非应用的模块;
控制器ID: 同应用(或同模块如果为模块下的控制器)下唯一标识控制器的字符串;
动作ID: 同控制器下唯一标识动作的字符串。
路由使用如下格式:
ControllerID/ActionID
如果属于模块下的控制器,使用如下格式:
ModuleID/ControllerID/ActionID
如果用户的请求地址为 http://hostname/index.php?r=site/index , 会执行site 控制器的index 操作。 更多关于处理路由的详情请参阅 路由 一节。
创建控制器
在yii\web\Application网页应用中,控制器应继承yii\web\Controller 或它的子类。 同理在yii\console\Application控制台应用中,控制器继承yii\console\Controller 或它的子类。 如下代码定义一个 site 控制器:
namespace app\
use yii\web\C
class SiteController extends Controller
通常情况下,控制器用来处理请求有关的资源类型,因此控制器ID通常为和资源有关的名词。 例如使用article作为处理文章的控制器ID。
控制器ID应仅包含英文小写字母、数字、下划线、中横杠和正斜杠, 例如 article 和 post-comment 是真是的控制器ID,article?,PostComment, admin\post不是控制器ID。
控制器Id可包含子目录前缀,例如 admin/article 代表 yii\base\Application::controllerNamespace 控制器命名空间下 admin子目录中 article 控制器。 子目录前缀可为英文大小写字母、数字、下划线、正斜杠,其中正斜杠用来区分多级子目录(如 panels/admin)。
控制器类命名
控制器ID遵循以下规则衍生控制器类名:
将用正斜杠区分的每个单词第一个字母转为大写。注意如果控制器ID包含正斜杠,只将最后的正斜杠后的部分第一个字母转为大写;
去掉中横杠,将正斜杠替换为反斜杠;
增加Controller后缀;
在前面增加yii\base\Application::controllerNamespace控制器命名空间.
下面为一些示例,假设yii\base\Application::controllerNamespace控制器命名空间为 app\controllers:
article 对应 app\controllers\ArticleC
post-comment 对应 app\controllers\PostCommentC
admin/post-comment 对应 app\controllers\admin\PostCommentC
adminPanels/post-comment 对应 app\controllers\adminPanels\PostCommentController.
控制器类必须能被 自动加载,所以在上面的例子中, 控制器article 类应在 别名 为@app/controllers/ArticleController.php的文件中定义, 控制器admin/post2-comment应在@app/controllers/admin/Post2CommentController.php文件中。
补充: 最后一个示例 admin/post2-comment 表示你可以将控制器放在 yii\base\Application::controllerNamespace控制器命名空间下的子目录中, 在你不想用 模块 的情况下给控制器分类,这种方式很有用。
控制器部署
可通过配置 yii\base\Application::controllerMap 来强制上述的控制器ID和类名对应, 通常用在使用第三方不能掌控类名的控制器上。
配置 应用配置 中的application configuration,如下所示:
'controllerMap' =& [
// 用类名申明 "account" 控制器
'account' =& 'app\controllers\UserController',
// 用配置数组申明 "article" 控制器
'article' =& [
'class' =& 'app\controllers\PostController',
'enableCsrfValidation' =& false,
默认控制器
每个应用有一个由yii\base\Application::defaultRoute属性指定的默认控制器; 当请求没有指定 路由,该属性值作为路由使用。 对于yii\web\Application网页应用,它的值为 'site', 对于 yii\console\Application控制台应用,它的值为 help, 所以URL为 http://hostname/index.php 表示由 site 控制器来处理。
可以在 应用配置 中修改默认控制器,如下所示:
'defaultRoute' =& 'main',
创建动作可简单地在控制器类中定义所谓的 动作方法 来完成,动作方法必须是以action开头的公有方法。 动作方法的返回值会作为响应数据发送给终端用户,如下代码定义了两个动作 index 和 hello-world:
namespace app\
use yii\web\C
class SiteController extends Controller
public function actionIndex()
return $this-&render('index');
public function actionHelloWorld()
return 'Hello World';
动作通常是用来执行资源的特定动作,因此,动作ID通常为动词,如view, update等。
动作ID应仅包含英文小写字母、数字、下划线和中横杠,动作ID中的中横杠用来分隔单词。 例如view, update2, comment-post是真实的操作ID,view?, Update不是操作ID.
可通过两种方式创建动作ID,内联动作和独立动作。内联动作在控制器类中定义为方法;独立动作是继承yii\base\Action或它的子类的类。 内联动作容易创建,在无需重用的情况下优先使用; 独立动作相反,主要用于多个控制器重用,或重构为扩展。
内联动作指的是根据我们刚描述的动作方法。
动作方法的名字是根据操作ID遵循如下规则衍生:
将每个单词的第一个字母转为大写;
去掉中横杠;
增加action前缀.
例如index 转成 actionIndex, hello-world 转成 actionHelloWorld。
注意: 操作方法的名字大小写敏感,如果方法名称为ActionIndex不会认为是操作方法, 所以请求index操作会返回一个异常,也要注意操作方法必须是公有的,私有或者受保护的方法不能定义成内联操作。
因为容易创建,内联动作是最常用的动作,但是如果你计划在不同地方重用相同的动作, 或者你想重新分配一个动作,需要考虑定义它为独立动作。
独立动作通过继承yii\base\Action或它的子类来定义。 例如Yii发布的yii\web\ViewAction和yii\web\ErrorAction都是独立操作。
要使用独立动作,需要通过控制器中覆盖yii\base\Controller::actions()方法在action map中申明,如下例所示:
public function actions()
// 用类来申明"error" 操作
'error' =& 'yii\web\ErrorAction',
// 用配置数组申明 "view" 操作
'view' =& [
'class' =& 'yii\web\ViewAction',
'viewPrefix' =& '',
如上所示, actions() 方法返回键为动作ID、值为对应动作类名或数组configurations 的数组。 和内联动作不同,独立动作ID可包含任意字符,只要在actions() 方法中申明.
为创建一个独立动作类,需要继承yii\base\Action 或它的子类,并实现公有的名称为run()的方法, run() 方法的角色和动作方法类似,例如:
namespace app\
use yii\base\A
class HelloWorldAction extends Action
public function run()
return "Hello World";
动作方法或独立动作的run()方法的返回值非常重要,它表示对应动作结果。
返回值可为 响应 对象,作为响应发送给终端用户。
对于yii\web\Application网页应用,返回值可为任意数据, 它赋值给yii\web\Response::data, 最终转换为字符串来展示响应内容。
对于yii\console\Application控制台应用,返回值可为整数, 表示命令行下执行的 yii\console\Response::exitStatus 退出状态。
在上面的例子中,动作结果都为字符串,作为响应数据发送给终端用户,下例显示一个动作通过 返回响应对象(因为yii\web\Controller::redirect()方法返回一个响应对象)可将用户浏览器跳转到新的URL。
public function actionForward()
// 用户浏览器跳转到
return $this-&redirect('');
内联动作的动作方法和独立动作的 run() 方法可以带参数,称为动作参数。 参数值从请求中获取,对于yii\web\Application网页应用, 每个动作参数的值从$_GET中获得,参数名作为键; 对于yii\console\Application控制台应用, 动作参数对应命令行参数。
如下例,动作view (内联动作) 申明了两个参数 $id 和 $version。
namespace app\
use yii\web\C
class PostController extends Controller
public function actionView($id, $version = null)
动作参数会被不同的参数填入,如下所示:
http://hostname/index.php?r=post/view&id=123: $id 会填入'123',$version 仍为 null 空因为没有version请求参数;
http://hostname/index.php?r=post/view&id=123&version=2: $id 和 $version 分别填入 '123' 和 '2';
http://hostname/index.php?r=post/view: 会抛出yii\web\BadRequestHttpException 异常 因为请求没有提供参数给必须赋值参数$id;
http://hostname/index.php?r=post/view&id[]=123: 会抛出yii\web\BadRequestHttpException 异常 因为$id 参数收到数字值['123']而不是字符串.
如果想让动作参数接收数组值,需要指定$id为array,如下所示:
public function actionView(array $id, $version = null)
现在如果请求为 http://hostname/index.php?r=post/view&id[]=123, 参数 $id 会使用数组值['123'], 如果请求为http://hostname/index.php?r=post/view&id=123, 参数 $id 会获取相同数组值,因为无类型的'123'会自动转成数组。
上述例子主要描述网页应用的操作参数,对于控制台应用,更多详情请参阅控制台命令。
每个控制器都有一个由 yii\base\Controller::defaultAction 属性指定的默认动作, 当路由 只包含控制器ID,会使用所请求的控制器的默认操作。
默认动作默认为 index,如果想修改默认动作,只需简单地在控制器类中覆盖这个属性,如下所示:
namespace app\
use yii\web\C
class SiteController extends Controller
public $defaultAction = 'home';
public function actionHome()
return $this-&render('home');
控制器生命周期
处理一个请求时,应用主体 会根据请求路由创建一个控制器,控制器经过以下生命周期来完成请求:
在控制器创建和配置后,yii\base\Controller::init() 方法会被调用。
控制器根据请求操作ID创建一个操作对象:
如果操作ID没有指定,会使用yii\base\Controller::defaultAction默认操作ID;
如果在yii\base\Controller::actions()找到操作ID,会创建一个独立操作;
如果操作ID对应操作方法,会创建一个内联操作;
否则会抛出yii\base\InvalidRouteException异常。
控制器按顺序调用应用主体、模块(如果控制器属于模块)、控制器的 beforeAction() 方法;
如果任意一个调用返回false,后面未调用的beforeAction()会跳过并且操作执行会被取消; action execution will be cancelled.
默认情况下每个 beforeAction() 方法会触发一个 beforeAction 事件,在事件中你可以追加事件处理操作;
控制器执行操作:
请求数据解析和填入到操作参数;
控制器按顺序调用控制器、模块(如果控制器属于模块)、应用主体的 afterAction() 方法;
默认情况下每个 afterAction() 方法会触发一个 afterAction 事件,在事件中你可以追加事件处理操作;
应用主体获取操作结果并赋值给响应.
在设计良好的应用中,控制器很精练,包含的操作代码简短; 如果你的控制器很复杂,通常意味着需要重构,转移一些代码到其他类中。
归纳起来,控制器
可访问 请求 数据;
可根据请求数据调用 模型 的方法和其他服务组件;
可使用 视图 构造响应;
不应处理应被模型处理的请求数据;
应避免嵌入HTML或其他展示代码,这些代码最好在 视图中处理.
这是一篇不错的文章,但是作者markdown用的不过关,希望再好好编辑一下。
这个是文档里面的吧
您需要登录后才可以评论。 |yii执行流程及其框架结构
注:此文是我全部复制,保存一份,特此感谢:
一&目录文件&&
|-framework&&&&&框架核心库&&
|--base&&&&&&&&&底层类库文件夹,包
含CApplication(应用类,负责全局的用户请求处理,它管理的应用组件集,将提供特定功能给整个应用程序),CComponent(组件类,该
文件包含了基于组件和事件驱动编程的基础类,从版本1.1.0开始,一个行为的属性(或者它的公共成员变量或它通过getter和/或setter方
法??定义的属性)可以通过组件的访问来调用),CBehavior(行为类,主要负责声明事件和相应事件处理程序的方法、将对象的行为附加到组件等
等),CModel(模型类,为所有的数据模型提供的基类),CModule(是模块和应用程序的基类,主要负责应用组件和子模块)等等&&
|--caching&&&&&&所有缓存方法,其中包含了Memcache缓存,APC缓存,数据缓存,CDummyCache虚拟缓存,CEAcceleratorCache缓存等等各种缓存方法&&
|--cli&&&&&&&&&&YII项目生成脚本&&
|--collections&&用php语言构造传统OO语言的数据存储单元。如:队列,栈,哈希表等等&&
|--console&&&&&&YII控制台&&
|--db&&&&&&&&&&&数据库操作类&&
|--gii&&&&&&&&&&YII&代码生成器(脚手架),能生成包括模型,控制器,视图等代码&&
|--i18n&&&&&&&&&YII&多语言,提供了各种语言的本地化数据,信息、文件的翻译服务、本地化日期和时间格式,数字等&&
|--logging&&&&&&日
志组件,YII提供了灵活和可扩展的日志记录功能。消息记录可分为根据日志级别和信息类别。应用层次和类别过滤器,可进一步选择的消息路由到不同的目的
地,例如文件,电子邮件,浏览器窗口,等等|--messages&&&&&&提示信息的多语言&&
|--test&&&&&&&&&&YII提供的测试,包括单元测试和功能测试&&
|--utils&&&&&&&&&提供了常用的格式化方法&&
|--validators&&&&提供了各种验证方法&&
|--vendors&&&&&&&这个文件夹包括第三方由Yii框架使用的资料库&&
|--views&&&&&&&&&提供了YII错误、日志、配置文件的多语言视图&&
|--web&&&&&&&&&&&YII所有开发应用的方法&&
|---actions&&&&&&控制器操作类&&
|---auth&&&&&&&&&权限认识类,包括身份认证,访问控制过滤,基本角色的访问控制等&&
|---filters&&&&&&过滤器,可被配置在控制器动作执行之前或之后执行。例如,&访问控制过滤器将被执行以确保在执行请求的动作之前用户已通过身份验证;性能过滤器可用于测量控制器执行所用的时间&&
|---form&&&&&&&&&表单生成方法&&
|---helpers&&&&&&视图助手,包含GOOGLE&AJAX&API,创建HTML,JSON,JAVASCRIPT相关功能&&
|---js&&&&&&&&&&&JS库&&
|---renderers&&&&视图渲染组件&&
|---services&&&&&封装SoapServer并提供了一个基于WSDL的Web服务&&
|---widgets&&&&&&部件&&
|---CArrayDataProvider.php&&&&&&&可以配置的排序和分页属性自定义排序和分页的行为&&
|---CActiveDataProvider.php&&&&&&ActiveRecord方法类&&
|---CController.php&&&&&&&&&&&&&&控制器方法,主要负责协调模型和视图之间的交互&&
|---CPagination.php&&&&&&&&&&&&&&分页类&&
|---CUploadedFile.php&&&&&&&&&&&&上传文件类&&
|---CUrlManager.php&&&&&&&&&&&&&&URL管理&&
|---CWebModule.php&&&&&&&&&&&&&&&应用模块管理,应用程序模块可被视为一个独立的子应用&&
等等方法&&
|--.htaccess&&&&&&&&&&&&&&&&&&&&&&重定向文件&&
|--yii.php&&&&&&&&&&&&&&&&&&&&&&&&引导文件&&
|--YiiBase.php&&&&&&&&&&&&&&&&&&&&YiiBase类最主要的功能是注册了自动加载类方法,加载框架要用到所有接口。&&
|--yiic&&&&&&&&&&&&&&&&&&&&&&&&&&&Yii&LINUX&命令行脚本&&
|--yiic.bat&&&&&&&&&&&&&&&&&&&&&&&YII&WINDOW&命令行脚本&&
|--yiilite.php&&&&&&&&&&&&&&&&&&&&它是一些常用到的&Yii&类文件的合并文件。在文件中,注释和跟踪语句都被去除。因此,使用&yiilite.php&将减少被引用的文件数量并避免执行跟踪语句&&
二&源码分析&&
网站的唯一入口程序&index.php&:&&
&&&1.&$yii=dirname(__FILE__).'/../framework/yii.php';&&
&&&2.&$config=dirname(__FILE__).'/protected/config/main.php';&&
&&&4.&//&remove&the&following&line&when&in&production&mode&&
&&&5.&defined('YII_DEBUG')&or&define('YII_DEBUG',true);&&
&&&7.&require_once($yii);&&
&&&8.&Yii::createWebApplication($config)-&run();&&
上面的require_once($yii)&引用出了后面要用到的全局类Yii,Yii类是YiiBase类的完全继承:&&
&&&1.&class&Yii&extends&YiiBase&&
系统的全局访问都是通过Yii类(即YiiBase类)来实现的,Yii类的成员和方法都是static类型。&&
2.&类加载&&
Yii利用PHP5提供的spl库来完成类的自动加载。在YiiBase.php&文件结尾处&&
&&&1.&spl_autoload_register(array('YiiBase','autoload'));&&
将YiiBase类的静态方法autoload&注册为类加载器。&PHP&autoload&的简单原理就是执行&new&创建对象或通过类名访问静态成员时,系统将类名传递给被注册的类加载器函数,类加载器函数根据类名自行找到对应的类文件并include&。&&
下面是YiiBase类的autoload方法:&&
&&&1.&public&static&function&autoload($className)&&
&&&3.&&&&//&use&include&so&that&the&error&PHP&file&may&appear&&
&&&4.&&&&if(isset(self::$_coreClasses[$className]))&&
&&&5.&&&&&include(YII_PATH.self::$_coreClasses[$className]);&&
&&&6.&&&&else&if(isset(self::$_classes[$className]))&&
&&&7.&&&&&include(self::$_classes[$className]);&&
&&&8.&&&&else&
&&&9.&&&&&include($className.'.php');&&
可以看到YiiBase的静态成员$_coreClasses&数组里预先存放着Yii系统自身用到的类对应的文件路径:&&
&&&1.&private&static&$_coreClasses=array(&&
&&&2.&&&&'CApplication'&=&&'/base/CApplication.php',&&
&&&3.&&&&'CBehavior'&=&&'/base/CBehavior.php',&&
&&&4.&&&&'CComponent'&=&&'/base/CComponent.php',&&
&&&5.&&&&...&&
非&coreClasse&的类注册在YiiBase的$_classes&数组中:&&
private&static&$_classes=array();&&
其他的类需要用Yii::import()讲类路径导入PHP&include&paths&中,直接&&
include($className.'.php')&&
3.&CWebApplication的创建&&
回到前面的程序入口的&Yii::createWebApplication($config)-&run();&&
&&&1.&public&static&function&createWebApplication($config=null)&&
&&&3.&&&&return&new&CWebApplication($config);&&
现在autoload机制开始工作了。&&
当系统&执行&new&CWebApplication()&的时候,会自动&&
include(YII_PATH.'/base/CApplication.php')&&
将main.php里的配置信息数组$config传递给CWebApplication创建出对象,并执行对象的run()&方法启动框架。&&
CWebApplication类的继承关系&&
CWebApplication&-&&CApplication&-&&CModule&-&&CComponent&&
$config先被传递给CApplication的构造函数&&
&&&1.&public&function&__construct($config=null)&&
&&&3.&&&&Yii::setApplication($this);&&
&&&5.&&&&//&set&basePath&at&early&as&possible&to&avoid&trouble&&
&&&6.&&&&if(is_string($config))&&
&&&7.&&&&&$config=require($config);&&
&&&8.&&&&if(isset($config['basePath']))&&
&&&9.&&&&{&&
&&10.&&&&&$this-&setBasePath($config['basePath']);&&
&&11.&&&&&unset($config['basePath']);&&
&&12.&&&&}&&
&&13.&&&&else&
&&14.&&&&&$this-&setBasePath('protected');&&
&&15.&&&&Yii::setPathOfAlias('application',$this-&getBasePath());&&
&&16.&&&&Yii::setPathOfAlias('webroot',dirname($_SERVER['SCRIPT_FILENAME']));&&
&&18.&&&&$this-&preinit();&&
&&20.&&&&$this-&initSystemHandlers();&&
&&21.&&&&$this-&registerCoreComponents();&&
&&23.&&&&$this-&configure($config);&&
&&24.&&&&$this-&attachBehaviors($this-&behaviors);&&
&&25.&&&&$this-&preloadComponents();&&
&&27.&&&&$this-&init();&&
Yii::setApplication($this);&将自身的实例对象赋给Yii的静态成员$_app,以后可以通过&Yii::app()&来取得。&&
后面一段是设置CApplication&对象的_basePath&,指向&proteced&目录。&&
&&&1.&Yii::setPathOfAlias('application',$this-&getBasePath());&&
&&&2.&Yii::setPathOfAlias('webroot',dirname($_SERVER['SCRIPT_FILENAME']));&&
设置了两个系统路径别名&application&和&webroot,后面再import的时候可以用别名来代替实际的完整路径。别名配置存放在YiiBase的&$_aliases&数组中。&&
$this-&preinit();&&
预初始化。preinit()是在&CModule&类里定义的,没有任何动作。&&
$this-&initSystemHandlers()&方法内容:&&
&&&4.&protected&function&initSystemHandlers()&&
&&&6.&&&&if(YII_ENABLE_EXCEPTION_HANDLER)&&
&&&7.&&&&&set_exception_handler(array($this,'handleException'));&&
&&&8.&&&&if(YII_ENABLE_ERROR_HANDLER)&&
&&&9.&&&&&set_error_handler(array($this,'handleError'),error_reporting());&&&&
设置系统exception_handler和&error_handler,指向对象自身提供的两个方法。&&
4.&注册核心组件&&
$this-&registerCoreComponents();&&
代码如下:&&
&&&1.&protected&function&registerCoreComponents()&&
&&&3.&&&&parent::registerCoreComponents();&&
&&&5.&&&&$components=array(&&
&&&6.&&&&&'urlManager'=&array(&&
&&&7.&&&&&&'class'=&'CUrlManager',&&
&&&8.&&&&&),&&
&&&9.&&&&&'request'=&array(&&
&&10.&&&&&&'class'=&'CHttpRequest',&&
&&11.&&&&&),&&
&&12.&&&&&'session'=&array(&&
&&13.&&&&&&'class'=&'CHttpSession',&&
&&14.&&&&&),&&
&&15.&&&&&'assetManager'=&array(&&
&&16.&&&&&&'class'=&'CAssetManager',&&
&&17.&&&&&),&&
&&18.&&&&&'user'=&array(&&
&&19.&&&&&&'class'=&'CWebUser',&&
&&20.&&&&&),&&
&&21.&&&&&'themeManager'=&array(&&
&&22.&&&&&&'class'=&'CThemeManager',&&
&&23.&&&&&),&&
&&24.&&&&&'authManager'=&array(&&
&&25.&&&&&&'class'=&'CPhpAuthManager',&&
&&26.&&&&&),&&
&&27.&&&&&'clientScript'=&array(&&
&&28.&&&&&&'class'=&'CClientScript',&&
&&29.&&&&&),&&
&&30.&&&&);&&
&&32.&&&&$this-&setComponents($components);&&
注册了几个系统组件(Components)。&&
Components&是在&CModule&里定义和管理的,主要包括两个数组&&
&&&1.&private&$_components=array();&&
&&&2.&private&$_componentConfig=array();&&
每个&Component&都是&IApplicationComponent接口的实例,Componemt的实例存放在$_components&数组里,相关的配置信息存放在$_componentConfig数组里。配置信息包括Component&的类名和属性设置。&&
CWebApplication&对 象注册了以下几个
Component:urlManager,&request,session,assetManager,user,themeManager,authManager,clientScript。&CWebApplication
的parent&注册了以下几
个&Component:coreMessages,db,messages,errorHandler,securityManager,statePersister。&&
Component&在
YiiPHP里是个非常重要的东西,它的特征是可以通过&CModule&的&__get()&和&__set()&方法来访
问。&Component&注册的时候并不会创建对象实例,而是在程序里被第一次访问到的时候,由CModule&来负责(实际上就
是&Yii::app())创建。&&
5.&处理&$config&配置&&
继续,&$this-&configure($config);&&
configure()&还是在CModule&里:&&
&&&1.&public&function&configure($config)&&
&&&3.&&&&if(is_array($config))&&
&&&4.&&&&{&&
&&&5.&&&&&foreach($config&as&$key=&$value)&&
&&&6.&&&&&&$this-&$key=$value;&&
&&&7.&&&&}&&
实际上是把$config数组里的每一项传给&CModule&的&父类&CComponent&__set()&方法。&&
&&&1.&public&function&__set($name,$value)&&
&&&3.&&&&$setter='set'.$name;&&
&&&4.&&&&if(method_exists($this,$setter))&&
&&&5.&&&&&$this-&$setter($value);&&
&&&6.&&&&else&if(strncasecmp($name,'on',2)===0&&
&&&7.&&&&&&&&&&&&&&&&&&&method_exists($this,$name))&&
&&&8.&&&&{&&
&&&9.&&&&&//duplicating&getEventHandlers()&here&for&performance&&
&&10.&&&&&$name=strtolower($name);&&
&&11.&&&&&if(!isset($this-&_e[$name]))&&
&&12.&&&&&&$this-&_e[$name]=new&CL&&
&&13.&&&&&&$this-&_e[$name]-&add($value);&&
&&14.&&&&&}&&
&&15.&&&&&else&if(method_exists($this,'get'.$name))&&
&&16.&&&&&&throw&new&CException(Yii::t('yii','Property&"{class}.{property}"&is&read&only.',&&
&&17.&&&&&&array('{class}'=&get_class($this),&'{property}'=&$name)));&&
&&18.&&&&&else&
&&19.&&&&&&throw&new&CException(Yii::t('yii','Property&"{class}.{property}"&is&not&defined.',&&
&&20.&&&&&&array('{class}'=&get_class($this),&'{property}'=&$name)));&&
&&21.&&&&}&&
我们来看看:&&
if(method_exists($this,$setter))&&
根据这个条件,$config&数组里的basePath,&params,&modules,&import,&components&都被传递给相应的&setBasePath(),&setParams()&等方法里进行处理。&&
6、$config&之&import&&
其中&import&被传递给&CModule&的&setImport:&&
&&&1.&public&function&setImport($aliases)&&
&&&3.&&&&foreach($aliases&as&$alias)&&
&&&4.&&&&&Yii::import($alias);&&
Yii::import($alias)里的处理:&&
&&&1.&public&static&function&import($alias,$forceInclude=false)&&
&&&3.&&&&//&先判断$alias是否存在于YiiBase::$_imports[]&中,已存在的直接return,&避免重复import。&&
&&&4.&&&&if(isset(self::$_imports[$alias]))&//&previously&imported&&
&&&5.&&&&&return&self::$_imports[$alias];&&
&&&7.&&&&//&$alias类已定义,记入$_imports[],直接返回&&
&&&8.&&&&if(class_exists($alias,false))&&
&&&9.&&&&&return&self::$_imports[$alias]=$alias;&&
&&11.&&&&//&类似&urlManager&这样的已定义于$_coreClasses[]的类,或不含.的直接类名,记入$_imports[],直接返回&&
&&12.&&&&if(isset(self::$_coreClasses[$alias])&||&($pos=strrpos($alias,'.'))===false)&//&a&simple&class&name&&
&&13.&&&&{&&
&&14.&&&&&self::$_imports[$alias]=$alias;&&
&&15.&&&&&if($forceInclude)&&
&&16.&&&&&{&&
&&17.&&&&&&if(isset(self::$_coreClasses[$alias]))&//&a&core&class&&
&&18.&&&&&&&require(YII_PATH.self::$_coreClasses[$alias]);&&
&&19.&&&&&&else&
&&20.&&&&&&&require($alias.'.php');&&
&&21.&&&&&}&&
&&22.&&&&&return&$alias;&&
&&23.&&&&}&&
&&25.&&&&//&产生一个变量&$className,为$alias最后一个.后面的部分&&
&&26.&&&&//&这样的:'x.y.ClassNamer'&&
&&27.&&&&//&$className不等于&'*',&并且ClassNamer类已定义的,&&&&&&ClassNamer'&记入&$_imports[],直接返回&&
&&28.&&&&if(($className=(string)substr($alias,$pos+1))!=='*'&&&&class_exists($className,false))&&
&&29.&&&&&return&self::$_imports[$alias]=$className;&&
&&31.&&&&//&取得&$alias&里真实的路径部分并且路径有效&&
&&32.&&&&if(($path=self::getPathOfAlias($alias))!==false)&&
&&33.&&&&{&&
&&34.&&&&&//&$className!=='*',$className&记入&$_imports[]&&
&&35.&&&&&if($className!=='*')&&
&&36.&&&&&{&&
&&37.&&&&&&self::$_imports[$alias]=$className;&&
&&38.&&&&&&if($forceInclude)&&
&&39.&&&&&&&require($path.'.php');&&
&&40.&&&&&&else&
&&41.&&&&&&&self::$_classes[$className]=$path.'.php';&&
&&42.&&&&&&return&$className;&&
&&43.&&&&&}&&
&&44.&&&&&//&$alias是'system.web.*'这样的已*结尾的路径,将路径加到include_path中&&
&&45.&&&&&else&//&a&directory&&
&&46.&&&&&{&&
&&47.&&&&&&set_include_path(get_include_path().PATH_SEPARATOR.$path);&&
&&48.&&&&&&return&self::$_imports[$alias]=$path;&&
&&49.&&&&&}&&
&&50.&&&&}&&
&&51.&&&&else&
&&52.&&&&&throw&new&CException(Yii::t('yii','Alias&"{alias}"&is&invalid.&Make&sure&it&points&to&an&existing&directory&or&file.',&&
&&53.&&&&&&array('{alias}'=&$alias)));&&
7.&$config&之&components&&
$config&数组里的&$components&被传递给CModule&的setComponents($components)&&
&&&1.&public&function&setComponents($components)&&
&&&3.&&&&foreach($components&as&$id=&$component)&&
&&&4.&&&&{&&
&&&5.&&&&&if($component&instanceof&IApplicationComponent)&&
&&&6.&&&&&&$this-&setComponent($id,$component);&&
&&&7.&&&&&else&if(isset($this-&_componentConfig[$id]))&&
&&&8.&&&&&&$this-&_componentConfig[$id]=CMap::mergeArray($this-&_componentConfig[$id],$component);&&
&&&9.&&&&&else&
&&10.&&&&&&$this-&_componentConfig[$id]=$component;&&
&&11.&&&&}&&
$componen是IApplicationComponen的实例的时候,直接赋值:&&
$this-&setComponent($id,$component),&&
&&&1.&public&function&setComponent($id,$component)&&
&&&3.&&&&$this-&_components[$id]=$component;&&
&&&4.&&&&if(!$component-&getIsInitialized())&&
&&&5.&&&&&$component-&init();&&
如果$id已存在于_componentConfig[]中(前面注册的coreComponent),将$component&属性加进入。&&
其他的component将component属性存入_componentConfig[]中。&&
8.&$config&之&params&&
这个很简单&&
&&&1.&public&function&setParams($value)&&
&&&3.&&&&$params=$this-&getParams();&&
&&&4.&&&&foreach($value&as&$k=&$v)&&
&&&5.&&&&&$params-&add($k,$v);&&
configure&完毕!&&
9.&attachBehaviors&&
$this-&attachBehaviors($this-&behaviors);&&
空的,没动作&&
预创建组件对象&&
&&&1.&$this-&preloadComponents();&&
&&&3.&protected&function&preloadComponents()&&
&&&5.&&&&foreach($this-&preload&as&$id)&&
&&&6.&&&&&$this-&getComponent($id);&&
getComponent()&判断_components[]&数组里是否有&$id的实例,如果没有,就根据_componentConfig[$id]里的配置来创建组件对象,调用组件的init()方法,然后存入_components[$id]中。&&
10.&init()&&
$this-&init();&&
函数内:$this-&getRequest();&&
创建了Reques&组件并初始化。&&
11.&run()&&
&&&1.&public&function&run()&&
&&&3.&&&&$this-&onBeginRequest(new&CEvent($this));&&
&&&4.&&&&$this-&processRequest();&&
&&&5.&&&&$this-&onEndRequest(new&CEvent($this));&&
三&大概过程&&
application构造函数:&&
1&设置当前运行实例&&
2&获取配置参数&&
3&设置basepath&&
4&设置几个path;application,webroot&,ext&&
5&preinit&&
6&注册error、exception处理函数&initSystemHandlers&&
7&加载核心组件&registerCoreComponents&包括webapplication的和application的&&
8&设置配置文件&configure($config)&&
9&附加行为&$this-&attachBehaviors($this-&behaviors);&&
10处理加载config中的preload,//通过getComponent分别加载并初始化&$this-&preloadComponents();&&&
11&初始化init();&//加载CHttpRequest组件&&
1&处理onBeginRequest&&
2&processRequest();真正处理请求&&
3&处理onEndRequest&&
webapplication-&processRequest():&&
1&&如果配置文件设置了catchAllRequest&,&//&'catchAllRequest'=&array('site/error','p1'=&'1','p2'=&'2'),&&
&&&则所有请求都跳转到这个controller/action这个route,并且设置$_GET参数。&&
2&&分析url得到route,便于后面的控制器/动作创建&&
3&&执行runController&&&&&
runController:&&
1&创建controller,&createController(),创建失败,则抛出404错误&&
2&得到controller对象和actionID&&
3&控制器初始化&&$controller-&init();&&
4&最后执行&&&$controller-&run($actionID);//真正执行页面请求&&
控制器类&&
CController:默认控制器在CWebApplication::defaultController定义('site'),可以在配置文件修改&&
1&//根据actionID创建action对象,这里生成的action对象分为定义在controller内联动作和自定义action,比如CViewAction&&
&&$action=$this-&createAction($actionID),如果创建动作失败,missingAction抛出404错误&&
2&beforeControllerAction(beforeControllerAction定义在CWebApplication,有时也在module里面)为真,才执行runActionWithFilters;&&
3&afterControllerAction&&
runActionWithFilters($action,$this-&filters()):&&
1&//如果过滤器为空,直接运行runAction()&&
2&执行过滤器链&&
runAction():&&
1&beforeAction()返回真,才执行&&
2&执行$action-&runWithParams();注意:这里存在多态,每个action都可以实现这个方法,&因为CInlineAction自己实现了runWithParams()&&
3&第2步骤为真,才执行afterAction($action);&&
动作类&&默认动作在CController::$defaultAction定义('index'),可以在CController的继承类重新定义&&
runWithParams():&&
1&分为2种情况,1种是内联动作,1种是通过控制器的actions方法定义的外联动作。&&
2&内联动作&通过action+动作id作为动作处理函数&&
3&外联动作&通过调用run()函数来实现&&
4&如果动作方法参数个数大于0,执行runWithParamsInternal,否则直接执行动作方法。&&
runWithParamsInternal();&&
1&根据反射的方法对象得到方法的形参列表,从&控制器对象-&getActionParams()得到实参,&&
&&如果实参有形参要求的参数,取其值,不然取形参默认值,否则,出错。&&
2&调用动作方法&&&2种形式&1是action+动作id&,2是Caction的派生类(比如cviewaction)的run()&&
3&执行控制器的CController-&render方法;$controller-&render($view)&&
控制器类&&
CController:&&
render();&&
1&renderPartial();得到视图,//先得到contact页面的view文件内容,注意是用include的形式,所以其中的$this是指siteControlerd对象,&&
&&这里调用了renderFile();&&
2&&然后$output=$this-&renderFile($layoutFile,array('content'=&$output),true)&&
&&&把view中的内容插入到布局页面layouts的column1.php,&&&&'content'和layout的页面的$content变量相关&&
renderFile();&&
1&如果程序没有定义viewrender,则执行controller-&renderInternal();否则,执行$renderer=Yii::app()-&getViewRenderer())-&renderFile();&
view&sourceprint?发生404错误&&
errorHandler&在配置文件main中,'errorAction'&=&&'site/error',&&
**********************************************************&&
runActionWithFilters&&
CFilterChain(继承CList,提供数字索引存取功能,遍历)::create($this,$action,$filters)-&run();&&
首先创建过滤链,然后执行过滤&&
CFilterChain::create($controller,$action,$filters):&&
1&$chain=new&CFilterChain($controller,$action);创建一个过滤链$chain&
2&根据参数filters数组,遍历创建过滤器$filter(字符串:通过CInlineFilter::create或者&数组:Yii::createComponent),&&
&&并且初始化$filter::init,通过$chain-&add($filter)添加到过滤链中,并且返回这个过滤链$chain&
注意:如果是字符串,控制器类controller必须要有"filter"+过滤器名的方法。&&
$chain::run();&&
1&如果数字索引合法,得到$filter,然后执行$filter-&filter($this);&&
&&&1.1&$filter-&filter($this):&&
&&&&&&&1&执行动作的'filter'+过滤器名称的方法。//比如CController::filterAccessControl($filterChain);&&
&&&1.1.1&CController::filterAccessControl($filterChain):&&
&&&&&&&&&&1&$filter=new&CAccessControlF//新建过滤器&&
&&&&&&&&&&2&$filter-&setRules($this-&accessRules());//设置规则&&
&&&&&&&&&&3&$filter-&filter($filterChain)&&;//执行过滤&&
&&&&&&&&&&4&$filter-&preFilter($filterChain)为真,继续执行$filterChain-&run();&&
&&&&&&&&&&5&$filter-&postFilter($filterChain);//这个是在动作执行之后过滤&&
2&否则,说明过滤完毕,$this-&controller-&runAction($this-&action);&直接执行动作。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。}

我要回帖

更多关于 yii init 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信