yiiソース分析3
72192 ワード
転載は明記してください:The Viper http://www.cnblogs.com/TheViper/
前の章 CWebAppleicationの¥route=>get UrlManager->parseUrl($this->get Request();$route=controller/actiondを得る。
これは彼の後ろの$this->run Controller($route)です。
最後にcontrollerの例とactiondを返します。
その後CWebAppleicationのrunController($route)に戻ります。controler初期化時に実行します。これはサブクラスで書き換える必要があります。
$controller->run($actionID);Ccontrollerに移行する
それからrunAction WithFilters($action、$filters)です。filterがなければ、直接runAction($action)です。
$action->run WithParaams($this->getAct Paract().actionはCInline Actionの例である。
上のrunAction WithFilters($action、$filters)に戻ります。ファイトがあれば、CFilterCharin:create($this、$filters)->run();
明らかに、filterがあるとactionメソッドを実行する前に、filterフィルタリストを設定しなければなりません。
CFilterCharinは'appration.filters.Loging Filter+uplad_video'という構成はフィルタチェーンに解析されます。
フィルタチェーンの各項目はCInline FilterまたはCFilterの例である。
例えば私のLoging Filter
それから$filterCharin->runです。ここは間違いやすいです。
実は再度CFilterCharinの中のrun()を使って、中の$this->filterIndex++を注意して、これは少し再帰するようです。
フィルタがactionをフィルタするなら、このようにCFilterに行って、その後$filterCharin->run();CFilterCharinを返し、同時に$this->filterIndex++を返して、その後$filterCharin->run();。。。
私の'appication.filters.Loging Filter+uplad_video'は、フィルタリングのみです。Videoというactionは、CFilterCharinに戻ると、$this->filterIndexは1になりましたが、フィルタリストはフィルタの一例しかないので、今回は$this->controller->runAction($this->action);フィルタをセットしていない時に歩く$this->runアクションです。同じです
フィルターの分析が終わったら、何のデータ操作かなど、最後はレンダリング表示レンダーです。これは簡単すぎます。extract($data)はincludeの下でファイルを見ればいいです。
forward()の方法があって、別のcontroller/actionにジャンプして、本質はCWebApple plicationのrunControllerに帰って更に上の分析の過程に来ます。
最後に添付します。裁断のyii http://files.cnblogs.com/TheViper/framework.zip
前の章 CWebAppleicationの¥route=>get UrlManager->parseUrl($this->get Request();$route=controller/actiondを得る。
これは彼の後ろの$this->run Controller($route)です。
1 <?php
2 class CWebApplication extends CApplication {
3 public $controllerNamespace;
4 private $_controllerPath;
5 private $_viewPath;
6 private $_systemViewPath;
7 private $_controller;
8 public $controllerMap=array();
9 public function processRequest() {//
10 // urlManager , , controller/action string,
11 // , , $_REQUEST
12 $route = $this->getUrlManager ()->parseUrl ($this->getRequest());
13 $this->runController ( $route );
14 }
15 public function getRequest() {// request
16 return $this->getComponent ( 'request' );
17 }
18 protected function registerCoreComponents() {//
19 parent::registerCoreComponents ();
20 }
21 // contronller
22 public function runController($route) {
23 if (($ca = $this->createController ( $route )) !== null) {
24 list ( $controller, $actionID ) = $ca;
25 $oldController = $this->_controller;
26 $this->_controller = $controller;
27 $controller->init ();// , action ,
28 $controller->run ( $actionID );// controller action
29 $this->_controller = $oldController;
30 }
31 }
32 // controller , controller/action string $controller, $actionID
33 public function createController($route, $owner = null) {
34 if ($owner === null)
35 $owner = $this;
36 if (($route = trim ( $route, '/' )) === '')
37 $route = $owner->defaultController;
38
39 $route .= '/';
40 while ( ($pos = strpos ( $route, '/' )) !== false ) {
41 $id = substr ( $route, 0, $pos );
42 if (! preg_match ( '/^\w+$/', $id ))
43 return null;
44 $id = strtolower ( $id );
45 $route = ( string ) substr ( $route, $pos + 1 );
46 if (! isset ( $basePath )) // first segment
47 {
48 $basePath = $owner->getControllerPath ();
49 $controllerID = '';
50 } else {
51 $controllerID .= '/';
52 }
53 $className = ucfirst ( $id ) . 'Controller';
54 $classFile = $basePath . DIRECTORY_SEPARATOR . $className . '.php';
55
56 if (is_file ( $classFile )) {
57 if (! class_exists ( $className, false ))
58 require ($classFile);
59 if (class_exists ( $className, false ) && is_subclass_of ( $className, 'CController' )) {
60 $id [0] = strtolower ( $id [0] );
61 return array (
62 new $className ( $controllerID . $id, $owner === $this ? null : $owner ),
63 $this->parseActionParams ( $route )
64 );
65 }
66 return null;
67 }
68 $controllerID .= $id;
69 $basePath .= DIRECTORY_SEPARATOR . $id;
70 }
71 }
72 protected function parseActionParams($pathInfo) {
73 if (($pos = strpos ( $pathInfo, '/' )) !== false) {
74 $manager = $this->getUrlManager ();// urlManager, 。
75 $manager->parsePathInfo ( ( string ) substr ( $pathInfo, $pos + 1 ) );
76 $actionID = substr ( $pathInfo, 0, $pos );
77 return $manager->caseSensitive ? $actionID : strtolower ( $actionID );
78 } else
79 return $pathInfo;
80 }
81 public function getControllerPath() {
82 if ($this->_controllerPath !== null)
83 return $this->_controllerPath;
84 else
85 return $this->_controllerPath = $this->getBasePath () . DIRECTORY_SEPARATOR . 'controllers';
86 }
87 // ,
88 public function beforeControllerAction($controller, $action) {
89 return true;
90 }
91 public function afterControllerAction($controller, $action) {
92 }
93 protected function init() {
94 parent::init ();
95 }
96 }
$ca=$this->createController($route);createControllerの役割は、$routeのcontrollerとactionを分離し、controllerのインスタンスを作成することです。最後にcontrollerの例とactiondを返します。
その後CWebAppleicationのrunController($route)に戻ります。controler初期化時に実行します。これはサブクラスで書き換える必要があります。
1 class VideoController extends CController {
2 public function init() {
3 $this->db = Yii::app ()->db;
4 }
5 public function actionBroadcast() {
6 $b = $this->db->query ( "", array (1 ) );
7 $this->render ( "u_broadcast", array (
8 'b' => $b [0] ;
9 ) );
10 }
11 }
このようにVideo Controllerでは$this->dbでdbコンポーネントを呼び出すことができます。$controller->run($actionID);Ccontrollerに移行する
1 <?php
2 class CController {
3 protected $db;
4 public $defaultAction = 'index';
5 private $_id;
6 private $_action;
7 public function __construct($id, $module = null) {
8 $this->_id = $id;
9 }
10 public function init() {
11 }
12 // ,
13 public function filters() {
14 return array ();
15 }
16 public function run($actionID) {
17 // action
18 if (($action = $this->createAction ( $actionID )) !== null) {
19 $parent = Yii::app ();
20 if ($parent->beforeControllerAction ( $this, $action )) {
21 $this->runActionWithFilters ( $action, $this->filters () );
22 $parent->afterControllerAction ( $this, $action );
23 }
24 }
25 }
26 public function refresh($terminate = true, $anchor = '') {
27 $this->redirect ( Yii::app ()->getRequest ()->getUrl () . $anchor, $terminate );
28 }
29 public function redirect($url, $terminate = true, $statusCode = 302) {
30 Yii::app ()->getRequest ()->redirect ( $url, $terminate, $statusCode );
31 }
32 // controller filter
33 public function runActionWithFilters($action, $filters) {
34 if (empty ( $filters ))
35 $this->runAction ( $action );
36 else {
37 $priorAction = $this->_action;
38 $this->_action = $action;
39 CFilterChain::create ( $this, $action, $filters )->run ();
40 $this->_action = $priorAction;
41 }
42 }
43 public function runAction($action) {
44 $priorAction = $this->_action;
45 $this->_action = $action;
46 if ($this->beforeAction ( $action )) {
47 if ($action->runWithParams ( $this->getActionParams () ) === false)
48 $this->invalidActionParams ( $action );
49 else
50 $this->afterAction ( $action );
51 }
52 $this->_action = $priorAction;
53 }
54 //
55 public function render($view, $data = array()) {
56 if (isset ( $data ))
57 extract ( $data );
58 include VIEWS_DIR . "/" . $this->_id . "/" . $view . ".php";
59 }
60 public function renderFile($file, $data = array()) {
61 if (isset ( $data ))
62 extract ( $data );
63 include VIEWS_DIR . "/" . $file;
64 }
65 // controller/action,
66 public function forward($route) {
67 if (strpos ( $route, '/' ) === false)
68 $this->run ( $route );
69 else {
70 // controller ,
71 Yii::app ()->runController ( $route );
72 }
73 }
74 public function getActionParams() {
75 return $_GET;
76 }
77 public function createAction($actionID) {
78 if ($actionID === '')
79 $actionID = $this->defaultAction;
80 if (method_exists ( $this, 'action' . $actionID ) && strcasecmp ( $actionID, 's' ))
81 return new CInlineAction ( $this, $actionID );
82 }
83 public function getAction() {
84 return $this->_action;
85 }
86 public function setAction($value) {
87 $this->_action = $value;
88 }
89 public function getId() {
90 return $this->_id;
91 }
92 //
93 protected function beforeAction($action) {
94 return true;
95 }
96 protected function afterAction($action) {
97 }
98 }
$this->createAction($actionID);actionのインスタンスを作成しますそれからrunAction WithFilters($action、$filters)です。filterがなければ、直接runAction($action)です。
$action->run WithParaams($this->getAct Paract().actionはCInline Actionの例である。
1 <?php
2 class CInlineAction extends CAction
3 {
4 //
5 public function run()
6 {
7 $method='action'.$this->getId();
8 $this->getController()->$method();
9 }
10 //
11 public function runWithParams($params)
12 {
13 $methodName='action'.$this->getId();// action
14 $controller=$this->getController();
15 $method=new ReflectionMethod($controller, $methodName);//
16 if($method->getNumberOfParameters()>0)// >0
17 return $this->runWithParamsInternal($controller, $method, $params);
18 else
19 return $controller->$methodName();
20 }
21 }
アクション 1 <?php
2 abstract class CAction extends CComponent
3 {
4 private $_id;
5 private $_controller;
6 public function __construct($controller,$id)
7 {
8 $this->_controller=$controller;
9 $this->_id=$id;
10 }
11 public function getController()
12 {
13 return $this->_controller;
14 }
15 public function getId()
16 {
17 return $this->_id;
18 }
19 // 。 CController::runAction()
20 public function runWithParams($params)
21 {
22 $method=new ReflectionMethod($this, 'run');
23 if($method->getNumberOfParameters()>0)
24 return $this->runWithParamsInternal($this, $method, $params);
25 else
26 return $this->run();
27 }
28 //
29 protected function runWithParamsInternal($object, $method, $params)
30 {
31 $ps=array();
32 foreach($method->getParameters() as $i=>$param)
33 {
34 $name=$param->getName();
35 if(isset($params[$name]))
36 {
37 if($param->isArray())
38 $ps[]=is_array($params[$name]) ? $params[$name] : array($params[$name]);
39 elseif(!is_array($params[$name]))
40 $ps[]=$params[$name];
41 else
42 return false;
43 }
44 elseif($param->isDefaultValueAvailable())
45 $ps[]=$param->getDefaultValue();
46 else
47 return false;
48 }
49 $method->invokeArgs($object,$ps);// ,
50 return true;
51 }
52 }
これらの2つのカテゴリーは非常に簡単です。つまり、controllerクラスのaction方法を実行します。上のrunAction WithFilters($action、$filters)に戻ります。ファイトがあれば、CFilterCharin:create($this、$filters)->run();
明らかに、filterがあるとactionメソッドを実行する前に、filterフィルタリストを設定しなければなりません。
CFilterCharinは'appration.filters.Loging Filter+uplad_video'という構成はフィルタチェーンに解析されます。
フィルタチェーンの各項目はCInline FilterまたはCFilterの例である。
1 <?php
2 //
3 class CFilterChain extends CList {
4 public $controller;
5 public $action;
6 public $filterIndex = 0;
7 public function __construct($controller, $action) {
8 $this->controller = $controller;
9 $this->action = $action;
10 }
11 //
12 public static function create($controller, $action, $filters) {
13 $chain = new CFilterChain ( $controller, $action );
14 $actionID = $action->getId ();
15 foreach ( $filters as $filter ) {
16 if (is_string ( $filter )) // filterName [+|- action1 action2]
17 {
18 if (($pos = strpos ( $filter, '+' )) !== false || ($pos = strpos ( $filter, '-' )) !== false) {
19 $matched = preg_match ( "/\b{$actionID}\b/i", substr ( $filter, $pos + 1 ) ) > 0;
20 if (($filter [$pos] === '+') === $matched)
21 $filter = CInlineFilter::create ( $controller, trim ( substr ( $filter, 0, $pos ) ) );
22 } else
23 $filter = CInlineFilter::create ( $controller, $filter );
24 } elseif (is_array ( $filter )) // array('path.to.class [+|- action1, action2]','param1'=>'value1',...)
25 {
26 $filterClass = $filter [0];
27 unset ( $filter [0] );
28 //
29 if (($pos = strpos ( $filterClass, '+' )) !== false || ($pos = strpos ( $filterClass, '-' )) !== false) {
30 preg_match ( "/\b{$actionID}\b/i", substr ( $filterClass, $pos + 1 ), $a );
31 $matched = preg_match ( "/\b{$actionID}\b/i", substr ( $filterClass, $pos + 1 ) ) > 0;
32 // filterName+action, ,
33 if (($filterClass [$pos] === '+') === $matched) {
34 //
35 $filterClass = trim ( substr ( $filterClass, 0, $pos ) );
36 } else
37 continue;
38 }
39 $filter ['class'] = $filterClass;
40 $filter = Yii::createComponent ( $filter );
41 }
42
43 if (is_object ( $filter )) {
44 $filter->init ();
45 $chain->add ( $filter );//list
46 }
47 }
48 return $chain;
49 }
50 public function run() {
51 if ($this->offsetExists ( $this->filterIndex )) {// 0
52 //
53 $filter = $this->itemAt ( $this->filterIndex ++ );
54 $filter->filter ( $this );
55 } else
56 $this->controller->runAction ( $this->action );
57 }
58 }
'appication.filters.Loging Filter+uplad_video'という構成はCFilterのインスタンスを作成します。 1 <?php
2 class CFilter extends CComponent {
3 public function filter($filterChain) {
4 // ,
5 if ($this->preFilter ( $filterChain )) {
6 $filterChain->run ();
7 $this->postFilter ( $filterChain );
8 }
9 }
10 //
11 public function init() {
12 }
13 protected function preFilter($filterChain) {
14 return true;
15 }
16 protected function postFilter($filterChain) {
17 }
18 }
そして上のCFilterCharin::create($this、$action、$filters)->run();のrun()は、リクエストが解析されたactionであればuplad(u)です。video,yiiはLoging Filterの例を取り出します。例えば私のLoging Filter
1 <?php
2 class LoginFilter extends CFilter {
3 protected function preFilter($filterChain) {
4 if (! isset ( $_SESSION )) {
5 session_start ();
6 }
7 if (isset ( $_SESSION ['user'] ))
8 return true;
9 else {
10 setcookie ( "return", Yii::app ()->getRequest ()->getUrl (), time () + 360, '/' );
11 Yii::app ()->getRequest ()->redirect ( 'http://localhost/youtube/login', true, 302 );
12 return false;
13 }
14 }
15 protected function postFilter($filterChain) {
16 }
17 }
18 ?>
中は一つの前置と後置について、フィルタを有効にする必要があるaction方法について、それぞれaction方法を実行する前と後で自分で定義したpreFilter、postFilter方法を実行することを表しています。それから$filterCharin->runです。ここは間違いやすいです。
実は再度CFilterCharinの中のrun()を使って、中の$this->filterIndex++を注意して、これは少し再帰するようです。
フィルタがactionをフィルタするなら、このようにCFilterに行って、その後$filterCharin->run();CFilterCharinを返し、同時に$this->filterIndex++を返して、その後$filterCharin->run();。。。
私の'appication.filters.Loging Filter+uplad_video'は、フィルタリングのみです。Videoというactionは、CFilterCharinに戻ると、$this->filterIndexは1になりましたが、フィルタリストはフィルタの一例しかないので、今回は$this->controller->runAction($this->action);フィルタをセットしていない時に歩く$this->runアクションです。同じです
フィルターの分析が終わったら、何のデータ操作かなど、最後はレンダリング表示レンダーです。これは簡単すぎます。extract($data)はincludeの下でファイルを見ればいいです。
forward()の方法があって、別のcontroller/actionにジャンプして、本質はCWebApple plicationのrunControllerに帰って更に上の分析の過程に来ます。
最後に添付します。裁断のyii http://files.cnblogs.com/TheViper/framework.zip