您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
免费发信息
三六零分类信息网 > 宜宾分类信息网,免费分类信息发布

YII 的源码分析(二)

2024/4/7 9:33:53发布47次查看
上一篇简单分析了一下yii的流程,从创建一个应用,到屏幕上输出结果。这一次我来一个稍复杂一点的,重点在输出上,不再是简单的一行hello world,而是要经过view(视图)层的处理。
依然是demos目录,这次我们选择hangman,一个简单的猜字游戏。老规则,还是从入口处开始看。
index.php:
php// change the following paths if necessary$yii=dirname(__file__).'/../../framework/yii.php';$config=dirname(__file__).'/protected/config/main.php';// remove the following line when in production mode// defined('yii_debug') or define('yii_debug',true);require_once($yii);yii::createwebapplication($config)->run();
和helloworld应用相比,这次多了main.php,打开main看下源码:
phpreturn array( 'name'=>'hangman game', 'defaultcontroller'=>'game', 'components'=>array( 'urlmanager'=>array( 'urlformat'=>'path', 'rules'=>array( 'game/guess/'=>'game/guess', ), ), ),);
在我们以后的实际项目中,也是经常要用到配置文件的,所以我觉得有必要了解一下yii的配置文件--main.php
'name'=>'这里通常是定义网站的标题',也就是我们打开index.php时,在网页上显示的标题。
'defaultcontroller'=>'这里是默认的控制器',也就是我们的index.php后面没有指定控制器时系统采用的控制器,如果我们这里没有指出来,默认就是site
'components'=>'这里是组件的参数,用多维数组进行配置。' 具体的参数可以查看yii手册。
yii::createwebapplication($config)->run(); 上一次我们已经详细分析过它了,这里再简单的走一遍:
cwebapplication.php -> capplication.php -> __construct($config) :
$this->preinit(); $this->initsystemhandlers(); $this->registercorecomponents(); $this->configure($config); $this->attachbehaviors($this->behaviors); $this->preloadcomponents(); $this->init();
上次我们没有配置过程,所以$this->configure($config)什么也没有做,但是这次有配置参数,所以我们进去看看yii做了哪些操作:
capplication自己没有实现configure方法,是继承于cmodule.php的:
public function configure($config) { if(is_array($config)) { foreach($config as $key=>$value) $this->$key=$value; } }
代码非常简单,就是把配置参数的键做为类的属性名,value做为类的属性值进行了扩展。完成这一过程就运行capplication 上的run方法了。
public function run() { if($this->haseventhandler('onbeginrequest')) $this->onbeginrequest(new cevent($this)); register_shutdown_function(array($this,'end'),0,false); $this->processrequest(); if($this->haseventhandler('onendrequest')) $this->onendrequest(new cevent($this)); }
我们前面说过,这里只要关注 $this->processrequest(); 就可以了。运行的结果就是执行$this->runcontroller('');  
public function runcontroller($route) { if(($ca=$this->createcontroller($route))!==null) { list($controller,$actionid)=$ca; $oldcontroller=$this->_controller; $this->_controller=$controller; $controller->init(); $controller->run($actionid); $this->_controller=$oldcontroller; } else throw new chttpexception(404,yii::t('yii','unable to resolve the request {route}.', array('{route}'=>$route===''?$this->defaultcontroller:$route))); }
由于url是index.php,后面没有任何参数,所以都是走的默认控制器,也就是我们在main.php中设定的game. 所以$controller 就等于 controllers/gamecontroller.php, 通过上次的源码分析我们可以知道,在gamecontroller.php中没有init方法时,都是走的父类中定义的默认方法(实际上是一个空方法),
$controller->run($actionid); == gamecontroller->run(''); gamecontroller上没有实现run方法,于是又是去父类中找run
从class gamecontroller extends ccontroller 可以看出,父类是ccontroller , 找到相应的run方法:
public function run($actionid) { if(($action=$this->createaction($actionid))!==null) { if(($parent=$this->getmodule())===null) $parent=yii::app(); if($parent->beforecontrolleraction($this,$action)) { $this->runactionwithfilters($action,$this->filters()); $parent->aftercontrolleraction($this,$action); } } else $this->missingaction($actionid); }
前面已经分析过了,没有指定时,都是默认参数。那么此时的$actionid为空,actionid就是gamecontroller中定义的默认动作:public $defaultaction='play'; 
runactionwithfilters ---> runaction --> $action->runwithparams
这里的$action 需要从caction -> cinlineaction中去找

public function runwithparams($params) { $methodname='action'.$this->getid(); $controller=$this->getcontroller(); $method=new reflectionmethod($controller, $methodname); if($method->getnumberofparameters()>0) return $this->runwithparamsinternal($controller, $method, $params); else return $controller->$methodname(); }
走了这么多过程,和hello world的流程是差不多的。据上次的分析可以知道,这里执行了
$controller->$methodname(); 也就是gamecontroller->actionplay()
到此,我们本节的重点才真正开始:

public function actionplay() { static $levels=array( '10'=>'easy game; you are allowed 10 misses.', '5'=>'medium game; you are allowed 5 misses.', '3'=>'hard game; you are allowed 3 misses.', ); // if a difficulty level is correctly chosen if(isset($_post['level']) && isset($levels[$_post['level']])) { $this->word=$this->generateword(); $this->guessword=str_repeat('_',strlen($this->word)); $this->level=$_post['level']; $this->misses=0; $this->setpagestate('guessed',null); // show the guess page $this->render('guess'); } else { $params=array( 'levels'=>$levels, // if this is a post request, it means the level is not chosen 'error'=>yii::app()->request->ispostrequest, ); // show the difficulty level page $this->render('play',$params); } }
显然走的是else的逻辑,重点请看 $this->render('play',$params); 这个render方法这么面熟,很多框架中都有类似的方法,比如discuz,smarty,ci 等等. 纵观yii框架,rnder 在它整个mvc模式中,是v得以实现的重要骨干。所以有必要把它翻个底朝天。
在ccontroller.php中有这个方法:
public function render($view,$data=null,$return=false) { if($this->beforerender($view)) { $output=$this->renderpartial($view,$data,true); if(($layoutfile=$this->getlayoutfile($this->layout))!==false) $output=$this->renderfile($layoutfile,array('content'=>$output),true); $this->afterrender($view,$output); $output=$this->processoutput($output); if($return) return $output; else echo $output; } }
当我们echo $output=$this->renderpartial($view,$data,true);的时候,就发现,此时的$output已经就拿到我们最终的结果了。它对应的文件是views/game/play.php
也就是我们在index.php上最终看到的内容了。由于本次渲染比较简单,所以程序经过的流程也较少,但是从源码中可以看到,里边进行了许多的处理,比如主题什么的。本次就先分析到这。晚安!

以上就介绍了yii 的源码分析(二),包括了方面的内容,希望对php教程有兴趣的朋友有所帮助。
宜宾分类信息网,免费分类信息发布

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录