转载请注明:theviper http://www.cnblogs.com/theviper/
上一篇说到CWebApplication中的¥route=$this->getUrlManager ()->parseUrl ($this->getRequest());,得到$route=controler/actionid。
这篇说他后面的$this->runController ( $route );
<span> 1</span> <?<span>php
</span><span> 2</span> <span>class</span> CWebApplication <span>extends</span><span> CApplication {
</span><span> 3</span> <span>public</span> <span>$controllerNamespace</span><span>;
</span><span> 4</span> <span>private</span> <span>$_controllerPath</span><span>;
</span><span> 5</span> <span>private</span> <span>$_viewPath</span><span>;
</span><span> 6</span> <span>private</span> <span>$_systemViewPath</span><span>;
</span><span> 7</span> <span>private</span> <span>$_controller</span><span>;
</span><span> 8</span> <span>public</span> <span>$controllerMap</span>=<span>array</span><span>();
</span><span> 9</span> <span>public</span> <span>function</span> processRequest() {<span>//</span><span>开始执行请求
</span><span>10</span> <span> //获取urlManager组件,解析请求,得到controller/action这种格式的string,
</span><span>11</span> <span> //并且将隐藏参数与请求的参数一一对应,匹配起来,写入$_REQUEST中</span>
<span>12</span> <span>$route</span> = <span>$this</span>->getUrlManager ()->parseUrl (<span>$this</span>-><span>getRequest());
</span><span>13</span> <span>$this</span>->runController ( <span>$route</span><span> );
</span><span>14</span> <span> }
</span><span>15</span> <span>public</span> <span>function</span> getRequest() {<span>//</span><span>获取request组件</span>
<span>16</span> <span>return</span> <span>$this</span>->getComponent ( 'request'<span> );
</span><span>17</span> <span> }
</span><span>18</span> <span>protected</span> <span>function</span> registerCoreComponents() {<span>//</span><span>注册核心组件</span>
<span>19</span> parent::<span>registerCoreComponents ();
</span><span>20</span> <span> }
</span><span>21</span> <span>//</span><span>执行contronller</span>
<span>22</span> <span>public</span> <span>function</span> runController(<span>$route</span><span>) {
</span><span>23</span> <span>if</span> ((<span>$ca</span> = <span>$this</span>->createController ( <span>$route</span> )) !== <span>null</span><span>) {
</span><span>24</span> <span>list</span> ( <span>$controller</span>, <span>$actionID</span> ) = <span>$ca</span><span>;
</span><span>25</span> <span>$oldController</span> = <span>$this</span>-><span>_controller;
</span><span>26</span> <span>$this</span>->_controller = <span>$controller</span><span>;
</span><span>27</span> <span>$controller</span>->init ();<span>//</span><span>钩子,在执行action方法前调用,子类去实现</span>
<span>28</span> <span>$controller</span>->run ( <span>$actionID</span> );<span>//</span><span>开始转入controller类中action方法的执行</span>
<span>29</span> <span>$this</span>->_controller = <span>$oldController</span><span>;
</span><span>30</span> <span> }
</span><span>31</span> <span> }
</span><span>32</span> <span>//</span><span>创建controller类实例,从controller/action这种格式的string中解析出$controller, $actionID </span>
<span>33</span> <span>public</span> <span>function</span> createController(<span>$route</span>, <span>$owner</span> = <span>null</span><span>) {
</span><span>34</span> <span>if</span> (<span>$owner</span> === <span>null</span><span>)
</span><span>35</span> <span>$owner</span> = <span>$this</span><span>;
</span><span>36</span> <span>if</span> ((<span>$route</span> = <span>trim</span> ( <span>$route</span>, '/' )) === ''<span>)
</span><span>37</span> <span>$route</span> = <span>$owner</span>-><span>defaultController;
</span><span>38</span>
<span>39</span> <span>$route</span> .= '/'<span>;
</span><span>40</span> <span>while</span> ( (<span>$pos</span> = <span>strpos</span> ( <span>$route</span>, '/' )) !== <span>false</span><span> ) {
</span><span>41</span> <span>$id</span> = <span>substr</span> ( <span>$route</span>, 0, <span>$pos</span><span> );
</span><span>42</span> <span>if</span> (! <span>preg_match</span> ( '/^\w+$/', <span>$id</span><span> ))
</span><span>43</span> <span>return</span> <span>null</span><span>;
</span><span>44</span> <span>$id</span> = <span>strtolower</span> ( <span>$id</span><span> );
</span><span>45</span> <span>$route</span> = ( <span>string</span> ) <span>substr</span> ( <span>$route</span>, <span>$pos</span> + 1<span> );
</span><span>46</span> <span>if</span> (! <span>isset</span> ( <span>$basePath</span> )) <span>//</span><span> first segment</span>
<span>47</span> <span> {
</span><span>48</span> <span>$basePath</span> = <span>$owner</span>-><span>getControllerPath ();
</span><span>49</span> <span>$controllerID</span> = ''<span>;
</span><span>50</span> } <span>else</span><span> {
</span><span>51</span> <span>$controllerID</span> .= '/'<span>;
</span><span>52</span> <span> }
</span><span>53</span> <span>$className</span> = <span>ucfirst</span> ( <span>$id</span> ) . 'Controller'<span>;
</span><span>54</span> <span>$classFile</span> = <span>$basePath</span> . DIRECTORY_SEPARATOR . <span>$className</span> . '.php'<span>;
</span><span>55</span>
<span>56</span> <span>if</span> (<span>is_file</span> ( <span>$classFile</span><span> )) {
</span><span>57</span> <span>if</span> (! <span>class_exists</span> ( <span>$className</span>, <span>false</span><span> ))
</span><span>58</span> <span>require</span> (<span>$classFile</span><span>);
</span><span>59</span> <span>if</span> (<span>class_exists</span> ( <span>$className</span>, <span>false</span> ) && <span>is_subclass_of</span> ( <span>$className</span>, 'CController'<span> )) {
</span><span>60</span> <span>$id</span> [0] = <span>strtolower</span> ( <span>$id</span> [0<span>] );
</span><span>61</span> <span>return</span> <span>array</span><span> (
</span><span>62</span> <span>new</span> <span>$className</span> ( <span>$controllerID</span> . <span>$id</span>, <span>$owner</span> === <span>$this</span> ? <span>null</span> : <span>$owner</span> ),
<span>63</span> <span>$this</span>->parseActionParams ( <span>$route</span><span> )
</span><span>64</span> <span> );
</span><span>65</span> <span> }
</span><span>66</span> <span>return</span> <span>null</span><span>;
</span><span>67</span> <span> }
</span><span>68</span> <span>$controllerID</span> .= <span>$id</span><span>;
</span><span>69</span> <span>$basePath</span> .= DIRECTORY_SEPARATOR . <span>$id</span><span>;
</span><span>70</span> <span> }
</span><span>71</span> <span> }
</span><span>72</span> <span>protected</span> <span>function</span> parseActionParams(<span>$pathInfo</span><span>) {
</span><span>73</span> <span>if</span> ((<span>$pos</span> = <span>strpos</span> ( <span>$pathInfo</span>, '/' )) !== <span>false</span><span>) {
</span><span>74</span> <span>$manager</span> = <span>$this</span>->getUrlManager ();<span>//</span><span>再次获取urlManager,在上面第一次调用中已经导入。</span>
<span>75</span> <span>$manager</span>->parsePathInfo ( ( <span>string</span> ) <span>substr</span> ( <span>$pathInfo</span>, <span>$pos</span> + 1<span> ) );
</span><span>76</span> <span>$actionID</span> = <span>substr</span> ( <span>$pathInfo</span>, 0, <span>$pos</span><span> );
</span><span>77</span> <span>return</span> <span>$manager</span>->caseSensitive ? <span>$actionID</span> : <span>strtolower</span> ( <span>$actionID</span><span> );
</span><span>78</span> } <span>else</span>
<span>79</span> <span>return</span> <span>$pathInfo</span><span>;
</span><span>80</span> <span> }
</span><span>81</span> <span>public</span> <span>function</span><span> getControllerPath() {
</span><span>82</span> <span>if</span> (<span>$this</span>->_controllerPath !== <span>null</span><span>)
</span><span>83</span> <span>return</span> <span>$this</span>-><span>_controllerPath;
</span><span>84</span> <span>else</span>
<span>85</span> <span>return</span> <span>$this</span>->_controllerPath = <span>$this</span>->getBasePath () . DIRECTORY_SEPARATOR . 'controllers'<span>;
</span><span>86</span> <span> }
</span><span>87</span> <span>//</span><span>两个钩子,子类去实现</span>
<span>88</span> <span>public</span> <span>function</span> beforeControllerAction(<span>$controller</span>, <span>$action</span><span>) {
</span><span>89</span> <span>return</span> <span>true</span><span>;
</span><span>90</span> <span> }
</span><span>91</span> <span>public</span> <span>function</span> afterControllerAction(<span>$controller</span>, <span>$action</span><span>) {
</span><span>92</span> <span> }
</span><span>93</span> <span>protected</span> <span>function</span><span> init() {
</span><span>94</span> parent::<span>init ();
</span><span>95</span> <span> }
</span><span>96</span> }$ca = $this->createController ( $route ));createController的作用是将$route中的controller和action分离出来,并创建controller实例。
最后返回controller实例和actionid.
立即学习“PHP免费学习笔记(深入)”;
然后回到CWebApplication的runController($route),$controller->init ();在controller初始化时执行,这个需要在子类中重写,比如:
<span> 1</span> <span>class</span> VideoController <span>extends</span><span> CController {
</span><span> 2</span> <span>public</span> <span>function</span><span> init() {
</span><span> 3</span> <span>$this</span>->db = Yii::app ()-><span>db;
</span><span> 4</span> <span> }
</span><span> 5</span> <span>public</span> <span>function</span><span> actionBroadcast() {
</span><span> 6</span> <span>$b</span> = <span>$this</span>->db->query ( "", <span>array</span> (1<span> ) );
</span><span> 7</span> <span>$this</span>->render ( "u_broadcast", <span>array</span><span> (
</span><span> 8</span> 'b' => <span>$b</span> [0<span>] ;
</span><span> 9</span> <span> ) );
</span><span>10</span> <span> }
</span><span>11</span> } 这样在VideoController中便可以用$this->db调用db组件了。
$controller->run ( $actionID );转入Ccontroller.
<span> 1</span> <?<span>php
</span><span> 2</span> <span>class</span><span> CController {
</span><span> 3</span> <span>protected</span> <span>$db</span><span>;
</span><span> 4</span> <span>public</span> <span>$defaultAction</span> = 'index'<span>;
</span><span> 5</span> <span>private</span> <span>$_id</span><span>;
</span><span> 6</span> <span>private</span> <span>$_action</span><span>;
</span><span> 7</span> <span>public</span> <span>function</span> __construct(<span>$id</span>, <span>$module</span> = <span>null</span><span>) {
</span><span> 8</span> <span>$this</span>->_id = <span>$id</span><span>;
</span><span> 9</span> <span> }
</span><span>10</span> <span>public</span> <span>function</span><span> init() {
</span><span>11</span> <span> }
</span><span>12</span> <span>//</span><span>过滤方法,子类重写</span>
<span>13</span> <span>public</span> <span>function</span><span> filters() {
</span><span>14</span> <span>return</span> <span>array</span><span> ();
</span><span>15</span> <span> }
</span><span>16</span> <span>public</span> <span>function</span> run(<span>$actionID</span><span>) {
</span><span>17</span> <span>//</span><span>创建action实例</span>
<span>18</span> <span>if</span> ((<span>$action</span> = <span>$this</span>->createAction ( <span>$actionID</span> )) !== <span>null</span><span>) {
</span><span>19</span> <span>$parent</span> = Yii::<span>app ();
</span><span>20</span> <span>if</span> (<span>$parent</span>->beforeControllerAction ( <span>$this</span>, <span>$action</span><span> )) {
</span><span>21</span> <span>$this</span>->runActionWithFilters ( <span>$action</span>, <span>$this</span>-><span>filters () );
</span><span>22</span> <span>$parent</span>->afterControllerAction ( <span>$this</span>, <span>$action</span><span> );
</span><span>23</span> <span> }
</span><span>24</span> <span> }
</span><span>25</span> <span> }
</span><span>26</span> <span>public</span> <span>function</span> refresh(<span>$terminate</span> = <span>true</span>, <span>$anchor</span> = ''<span>) {
</span><span>27</span> <span>$this</span>->redirect ( Yii::app ()->getRequest ()->getUrl () . <span>$anchor</span>, <span>$terminate</span><span> );
</span><span>28</span> <span> }
</span><span>29</span> <span>public</span> <span>function</span> redirect(<span>$url</span>, <span>$terminate</span> = <span>true</span>, <span>$statusCode</span> = 302<span>) {
</span><span>30</span> Yii::app ()->getRequest ()->redirect ( <span>$url</span>, <span>$terminate</span>, <span>$statusCode</span><span> );
</span><span>31</span> <span> }
</span><span>32</span> <span>//</span><span>如果controller里面有filter</span>
<span>33</span> <span>public</span> <span>function</span> runActionWithFilters(<span>$action</span>, <span>$filters</span><span>) {
</span><span>34</span> <span>if</span> (<span>empty</span> ( <span>$filters</span><span> ))
</span><span>35</span> <span>$this</span>->runAction ( <span>$action</span><span> );
</span><span>36</span> <span>else</span><span> {
</span><span>37</span> <span>$priorAction</span> = <span>$this</span>-><span>_action;
</span><span>38</span> <span>$this</span>->_action = <span>$action</span><span>;
</span><span>39</span> CFilterChain::create ( <span>$this</span>, <span>$action</span>, <span>$filters</span> )-><span>run ();
</span><span>40</span> <span>$this</span>->_action = <span>$priorAction</span><span>;
</span><span>41</span> <span> }
</span><span>42</span> <span> }
</span><span>43</span> <span>public</span> <span>function</span> runAction(<span>$action</span><span>) {
</span><span>44</span> <span>$priorAction</span> = <span>$this</span>-><span>_action;
</span><span>45</span> <span>$this</span>->_action = <span>$action</span><span>;
</span><span>46</span> <span>if</span> (<span>$this</span>->beforeAction ( <span>$action</span><span> )) {
</span><span>47</span> <span>if</span> (<span>$action</span>->runWithParams ( <span>$this</span>->getActionParams () ) === <span>false</span><span>)
</span><span>48</span> <span>$this</span>->invalidActionParams ( <span>$action</span><span> );
</span><span>49</span> <span>else</span>
<span>50</span> <span>$this</span>->afterAction ( <span>$action</span><span> );
</span><span>51</span> <span> }
</span><span>52</span> <span>$this</span>->_action = <span>$priorAction</span><span>;
</span><span>53</span> <span> }
</span><span>54</span> <span>//</span><span>渲染视图</span>
<span>55</span> <span>public</span> <span>function</span> render(<span>$view</span>, <span>$data</span> = <span>array</span><span>()) {
</span><span>56</span> <span>if</span> (<span>isset</span> ( <span>$data</span><span> ))
</span><span>57</span> <span>extract</span> ( <span>$data</span><span> );
</span><span>58</span> <span>include</span> VIEWS_DIR . "/" . <span>$this</span>->_id . "/" . <span>$view</span> . ".php"<span>;
</span><span>59</span> <span> }
</span><span>60</span> <span>public</span> <span>function</span> renderFile(<span>$file</span>, <span>$data</span> = <span>array</span><span>()) {
</span><span>61</span> <span>if</span> (<span>isset</span> ( <span>$data</span><span> ))
</span><span>62</span> <span>extract</span> ( <span>$data</span><span> );
</span><span>63</span> <span>include</span> VIEWS_DIR . "/" . <span>$file</span><span>;
</span><span>64</span> <span> }
</span><span>65</span> <span>//</span><span>跳转到另一个controller/action,不过浏览器的地址没有变</span>
<span>66</span> <span>public</span> <span>function</span> forward(<span>$route</span><span>) {
</span><span>67</span> <span>if</span> (<span>strpos</span> ( <span>$route</span>, '/' ) === <span>false</span><span>)
</span><span>68</span> <span>$this</span>->run ( <span>$route</span><span> );
</span><span>69</span> <span>else</span><span> {
</span><span>70</span> <span>//</span><span>不在同一个controller里面,重新创建</span>
<span>71</span> Yii::app ()->runController ( <span>$route</span><span> );
</span><span>72</span> <span> }
</span><span>73</span> <span> }
</span><span>74</span> <span>public</span> <span>function</span><span> getActionParams() {
</span><span>75</span> <span>return</span> <span>$_GET</span><span>;
</span><span>76</span> <span> }
</span><span>77</span> <span>public</span> <span>function</span> createAction(<span>$actionID</span><span>) {
</span><span>78</span> <span>if</span> (<span>$actionID</span> === ''<span>)
</span><span>79</span> <span>$actionID</span> = <span>$this</span>-><span>defaultAction;
</span><span>80</span> <span>if</span> (<span>method_exists</span> ( <span>$this</span>, 'action' . <span>$actionID</span> ) && <span>strcasecmp</span> ( <span>$actionID</span>, 's'<span> ))
</span><span>81</span> <span>return</span> <span>new</span> CInlineAction ( <span>$this</span>, <span>$actionID</span><span> );
</span><span>82</span> <span> }
</span><span>83</span> <span>public</span> <span>function</span><span> getAction() {
</span><span>84</span> <span>return</span> <span>$this</span>-><span>_action;
</span><span>85</span> <span> }
</span><span>86</span> <span>public</span> <span>function</span> setAction(<span>$value</span><span>) {
</span><span>87</span> <span>$this</span>->_action = <span>$value</span><span>;
</span><span>88</span> <span> }
</span><span>89</span> <span>public</span> <span>function</span><span> getId() {
</span><span>90</span> <span>return</span> <span>$this</span>-><span>_id;
</span><span>91</span> <span> }
</span><span>92</span> <span>//</span><span>两个钩子</span>
<span>93</span> <span>protected</span> <span>function</span> beforeAction(<span>$action</span><span>) {
</span><span>94</span> <span>return</span> <span>true</span><span>;
</span><span>95</span> <span> }
</span><span>96</span> <span>protected</span> <span>function</span> afterAction(<span>$action</span><span>) {
</span><span>97</span> <span> }
</span><span>98</span> }$this->createAction ( $actionID );创建action实例.
然后是runActionWithFilters($action, $filters);如果没有filter(),直接runAction($action)。
$action->runWithParams ( $this->getActionParams () ).$action是CInlineAction实例。
<span> 1</span> <?<span>php
</span><span> 2</span> <span>class</span> CInlineAction <span>extends</span><span> CAction
</span><span> 3</span> <span>{
</span><span> 4</span> <span>//</span><span>执行该动作</span>
<span> 5</span> <span>public</span> <span>function</span><span> run()
</span><span> 6</span> <span> {
</span><span> 7</span> <span>$method</span>='action'.<span>$this</span>-><span>getId();
</span><span> 8</span> <span>$this</span>->getController()-><span>$method</span><span>();
</span><span> 9</span> <span> }
</span><span>10</span> <span>//</span><span>执行带提供的请求的参数的动作</span>
<span>11</span> <span>public</span> <span>function</span> runWithParams(<span>$params</span><span>)
</span><span>12</span> <span> {
</span><span>13</span> <span>$methodName</span>='action'.<span>$this</span>->getId();<span>//</span><span>拼接action方法</span>
<span>14</span> <span>$controller</span>=<span>$this</span>-><span>getController();
</span><span>15</span> <span>$method</span>=<span>new</span> ReflectionMethod(<span>$controller</span>, <span>$methodName</span>);<span>//</span><span>反射</span>
<span>16</span> <span>if</span>(<span>$method</span>->getNumberOfParameters()>0)<span>//</span><span>方法参数个数>0</span>
<span>17</span> <span>return</span> <span>$this</span>->runWithParamsInternal(<span>$controller</span>, <span>$method</span>, <span>$params</span><span>);
</span><span>18</span> <span>else</span>
<span>19</span> <span>return</span> <span>$controller</span>-><span>$methodName</span><span>();
</span><span>20</span> <span> }
</span><span>21</span> }CAction
<span> 1</span> <?<span>php
</span><span> 2</span> <span>abstract</span> <span>class</span> CAction <span>extends</span><span> CComponent
</span><span> 3</span> <span>{
</span><span> 4</span> <span>private</span> <span>$_id</span><span>;
</span><span> 5</span> <span>private</span> <span>$_controller</span><span>;
</span><span> 6</span> <span>public</span> <span>function</span> __construct(<span>$controller</span>,<span>$id</span><span>)
</span><span> 7</span> <span> {
</span><span> 8</span> <span>$this</span>->_controller=<span>$controller</span><span>;
</span><span> 9</span> <span>$this</span>->_id=<span>$id</span><span>;
</span><span>10</span> <span> }
</span><span>11</span> <span>public</span> <span>function</span><span> getController()
</span><span>12</span> <span> {
</span><span>13</span> <span>return</span> <span>$this</span>-><span>_controller;
</span><span>14</span> <span> }
</span><span>15</span> <span>public</span> <span>function</span><span> getId()
</span><span>16</span> <span> {
</span><span>17</span> <span>return</span> <span>$this</span>-><span>_id;
</span><span>18</span> <span> }
</span><span>19</span> <span>//</span><span>运行带有请求参数的对象。 这个方法通过CController::runAction()内部调用</span>
<span>20</span> <span>public</span> <span>function</span> runWithParams(<span>$params</span><span>)
</span><span>21</span> <span> {
</span><span>22</span> <span>$method</span>=<span>new</span> ReflectionMethod(<span>$this</span>, 'run'<span>);
</span><span>23</span> <span>if</span>(<span>$method</span>->getNumberOfParameters()>0<span>)
</span><span>24</span> <span>return</span> <span>$this</span>->runWithParamsInternal(<span>$this</span>, <span>$method</span>, <span>$params</span><span>);
</span><span>25</span> <span>else</span>
<span>26</span> <span>return</span> <span>$this</span>-><span>run();
</span><span>27</span> <span> }
</span><span>28</span> <span>//</span><span>执行一个带有命名参数的对象的方法</span>
<span>29</span> <span>protected</span> <span>function</span> runWithParamsInternal(<span>$object</span>, <span>$method</span>, <span>$params</span><span>)
</span><span>30</span> <span> {
</span><span>31</span> <span>$ps</span>=<span>array</span><span>();
</span><span>32</span> <span>foreach</span>(<span>$method</span>->getParameters() <span>as</span> <span>$i</span>=><span>$param</span><span>)
</span><span>33</span> <span> {
</span><span>34</span> <span>$name</span>=<span>$param</span>-><span>getName();
</span><span>35</span> <span>if</span>(<span>isset</span>(<span>$params</span>[<span>$name</span><span>]))
</span><span>36</span> <span> {
</span><span>37</span> <span>if</span>(<span>$param</span>-><span>isArray())
</span><span>38</span> <span>$ps</span>[]=<span>is_array</span>(<span>$params</span>[<span>$name</span>]) ? <span>$params</span>[<span>$name</span>] : <span>array</span>(<span>$params</span>[<span>$name</span><span>]);
</span><span>39</span> <span>elseif</span>(!<span>is_array</span>(<span>$params</span>[<span>$name</span><span>]))
</span><span>40</span> <span>$ps</span>[]=<span>$params</span>[<span>$name</span><span>];
</span><span>41</span> <span>else</span>
<span>42</span> <span>return</span> <span>false</span><span>;
</span><span>43</span> <span> }
</span><span>44</span> <span>elseif</span>(<span>$param</span>-><span>isDefaultValueAvailable())
</span><span>45</span> <span>$ps</span>[]=<span>$param</span>-><span>getDefaultValue();
</span><span>46</span> <span>else</span>
<span>47</span> <span>return</span> <span>false</span><span>;
</span><span>48</span> <span> }
</span><span>49</span> <span>$method</span>->invokeArgs(<span>$object</span>,<span>$ps</span>);<span>//</span><span>反射,执行</span>
<span>50</span> <span>return</span> <span>true</span><span>;
</span><span>51</span> <span> }
</span><span>52</span> }这两个类都很简单,就是执行controller类中的action方法。
回到上面的runActionWithFilters($action, $filters);如果有filter(),CFilterChain::create ( $this, $action, $filters )->run ();
显然,如果有filter的话必须在执行action方法前,就设置好filter过滤器列表。
CFilterChain就是将类似于'application.filters.LoginFilter+upload_video' 这种配置解析成过滤器链。
过滤器链的每一项是一个CInlineFilter或CFilter实例。
<span> 1</span> <?<span>php
</span><span> 2</span> <span>//</span><span>过滤器列表</span>
<span> 3</span> <span>class</span> CFilterChain <span>extends</span><span> CList {
</span><span> 4</span> <span>public</span> <span>$controller</span><span>;
</span><span> 5</span> <span>public</span> <span>$action</span><span>;
</span><span> 6</span> <span>public</span> <span>$filterIndex</span> = 0<span>;
</span><span> 7</span> <span>public</span> <span>function</span> __construct(<span>$controller</span>, <span>$action</span><span>) {
</span><span> 8</span> <span>$this</span>->controller = <span>$controller</span><span>;
</span><span> 9</span> <span>$this</span>->action = <span>$action</span><span>;
</span><span>10</span> <span> }
</span><span>11</span> <span>//</span><span>创建过滤器列表</span>
<span>12</span> <span>public</span> <span>static</span> <span>function</span> create(<span>$controller</span>, <span>$action</span>, <span>$filters</span><span>) {
</span><span>13</span> <span>$chain</span> = <span>new</span> CFilterChain ( <span>$controller</span>, <span>$action</span><span> );
</span><span>14</span> <span>$actionID</span> = <span>$action</span>-><span>getId ();
</span><span>15</span> <span>foreach</span> ( <span>$filters</span> <span>as</span> <span>$filter</span><span> ) {
</span><span>16</span> <span>if</span> (<span>is_string</span> ( <span>$filter</span> )) <span>//</span><span> filterName [+|- action1 action2]</span>
<span>17</span> <span> {
</span><span>18</span> <span>if</span> ((<span>$pos</span> = <span>strpos</span> ( <span>$filter</span>, '+' )) !== <span>false</span> || (<span>$pos</span> = <span>strpos</span> ( <span>$filter</span>, '-' )) !== <span>false</span><span>) {
</span><span>19</span> <span>$matched</span> = <span>preg_match</span> ( "/\b{<span>$actionID</span>}\b/i", <span>substr</span> ( <span>$filter</span>, <span>$pos</span> + 1 ) ) > 0<span>;
</span><span>20</span> <span>if</span> ((<span>$filter</span> [<span>$pos</span>] === '+') === <span>$matched</span><span>)
</span><span>21</span> <span>$filter</span> = CInlineFilter::create ( <span>$controller</span>, <span>trim</span> ( <span>substr</span> ( <span>$filter</span>, 0, <span>$pos</span><span> ) ) );
</span><span>22</span> } <span>else</span>
<span>23</span> <span>$filter</span> = CInlineFilter::create ( <span>$controller</span>, <span>$filter</span><span> );
</span><span>24</span> } <span>elseif</span> (<span>is_array</span> ( <span>$filter</span> )) <span>//</span><span> array('path.to.class [+|- action1, action2]','param1'=>'value1',...)</span>
<span>25</span> <span> {
</span><span>26</span> <span>$filterClass</span> = <span>$filter</span> [0<span>];
</span><span>27</span> <span>unset</span> ( <span>$filter</span> [0<span>] );
</span><span>28</span> <span>//</span><span>开始解析过滤器配置</span>
<span>29</span> <span>if</span> ((<span>$pos</span> = <span>strpos</span> ( <span>$filterClass</span>, '+' )) !== <span>false</span> || (<span>$pos</span> = <span>strpos</span> ( <span>$filterClass</span>, '-' )) !== <span>false</span><span>) {
</span><span>30</span> <span>preg_match</span> ( "/\b{<span>$actionID</span>}\b/i", <span>substr</span> ( <span>$filterClass</span>, <span>$pos</span> + 1 ), <span>$a</span><span> );
</span><span>31</span> <span>$matched</span> = <span>preg_match</span> ( "/\b{<span>$actionID</span>}\b/i", <span>substr</span> ( <span>$filterClass</span>, <span>$pos</span> + 1 ) ) > 0<span>;
</span><span>32</span> <span>//</span><span>如果是filterName+action,创建一个过滤器,否则忽略</span>
<span>33</span> <span>if</span> ((<span>$filterClass</span> [<span>$pos</span>] === '+') === <span>$matched</span><span>) {
</span><span>34</span> <span>//</span><span>解析出过滤器的类名</span>
<span>35</span> <span>$filterClass</span> = <span>trim</span> ( <span>substr</span> ( <span>$filterClass</span>, 0, <span>$pos</span><span> ) );
</span><span>36</span> } <span>else</span>
<span>37</span> <span>continue</span><span>;
</span><span>38</span> <span> }
</span><span>39</span> <span>$filter</span> ['class'] = <span>$filterClass</span><span>;
</span><span>40</span> <span>$filter</span> = Yii::createComponent ( <span>$filter</span><span> );
</span><span>41</span> <span> }
</span><span>42</span>
<span>43</span> <span>if</span> (<span>is_object</span> ( <span>$filter</span><span> )) {
</span><span>44</span> <span>$filter</span>-><span>init ();
</span><span>45</span> <span>$chain</span>->add ( <span>$filter</span> );<span>//</span><span>list添加过滤器</span>
<span>46</span> <span> }
</span><span>47</span> <span> }
</span><span>48</span> <span>return</span> <span>$chain</span><span>;
</span><span>49</span> <span> }
</span><span>50</span> <span>public</span> <span>function</span><span> run() {
</span><span>51</span> <span>if</span> (<span>$this</span>->offsetExists ( <span>$this</span>->filterIndex )) {<span>//</span><span>过滤器列表个数不为0
</span><span>52</span> <span> //取出过滤器实例</span>
<span>53</span> <span>$filter</span> = <span>$this</span>->itemAt ( <span>$this</span>->filterIndex ++<span> );
</span><span>54</span> <span>$filter</span>->filter ( <span>$this</span><span> );
</span><span>55</span> } <span>else</span>
<span>56</span> <span>$this</span>->controller->runAction ( <span>$this</span>-><span>action );
</span><span>57</span> <span> }
</span><span>58</span> }'application.filters.LoginFilter+upload_video' 这种配置会创建CFilter实例。
<span> 1</span> <?<span>php
</span><span> 2</span> <span>class</span> CFilter <span>extends</span><span> CComponent {
</span><span> 3</span> <span>public</span> <span>function</span> filter(<span>$filterChain</span><span>) {
</span><span> 4</span> <span>//</span><span>前置,后置方法</span>
<span> 5</span> <span>if</span> (<span>$this</span>->preFilter ( <span>$filterChain</span><span> )) {
</span><span> 6</span> <span>$filterChain</span>-><span>run ();
</span><span> 7</span> <span>$this</span>->postFilter ( <span>$filterChain</span><span> );
</span><span> 8</span> <span> }
</span><span> 9</span> <span> }
</span><span>10</span> <span>//</span><span>钩子</span>
<span>11</span> <span>public</span> <span>function</span><span> init() {
</span><span>12</span> <span> }
</span><span>13</span> <span>protected</span> <span>function</span> preFilter(<span>$filterChain</span><span>) {
</span><span>14</span> <span>return</span> <span>true</span><span>;
</span><span>15</span> <span> }
</span><span>16</span> <span>protected</span> <span>function</span> postFilter(<span>$filterChain</span><span>) {
</span><span>17</span> <span> }
</span><span>18</span> }然后是上面的CFilterChain::create ( $this, $action, $filters )->run ();中的run(),如果请求被解析成的action是upload_video,yii就会取出LoginFilter实例。
比如我的LoginFilter
<span> 1</span> <?<span>php
</span><span> 2</span> <span>class</span> LoginFilter <span>extends</span><span> CFilter {
</span><span> 3</span> <span>protected</span> <span>function</span> preFilter(<span>$filterChain</span><span>) {
</span><span> 4</span> <span>if</span> (! <span>isset</span> ( <span>$_SESSION</span><span> )) {
</span><span> 5</span> <span>session_start</span><span> ();
</span><span> 6</span> <span> }
</span><span> 7</span> <span>if</span> (<span>isset</span> ( <span>$_SESSION</span> ['user'<span>] ))
</span><span> 8</span> <span>return</span> <span>true</span><span>;
</span><span> 9</span> <span>else</span><span> {
</span><span>10</span> <span>setcookie</span> ( "return", Yii::app ()->getRequest ()->getUrl (), <span>time</span> () + 360, '/'<span> );
</span><span>11</span> Yii::app ()->getRequest ()->redirect ( 'http://localhost/youtube/login', <span>true</span>, 302<span> );
</span><span>12</span> <span>return</span> <span>false</span><span>;
</span><span>13</span> <span> }
</span><span>14</span> <span> }
</span><span>15</span> <span>protected</span> <span>function</span> postFilter(<span>$filterChain</span><span>) {
</span><span>16</span> <span> }
</span><span>17</span> <span>}
</span><span>18</span> ?>里面就一个前置和后置,表示对于需要启用过滤器的action方法,分别在执行action方法之前和之后执行自己定义的preFilter,postFilter方法。
然后是$filterChain->run ();这里很容易出错。
其实是再次用CFilterChain里面的run(),注意到里面的$this->filterIndex++,这有点像递归.
如果过滤器要过滤对个action,就像这样去CFilter,然后$filterChain->run ();返回CFilterChain,同时$this->filterIndex++,然后继续$filterChain->run ();。。。。。。
对于我的'application.filters.LoginFilter+upload_video',只过滤upload_video这一个action,所以当返回CFilterChain时,$this->filterIndex已经变成1了,而过滤器列表只有一个过滤器实例,所以这次就会走$this->controller->runAction ( $this->action );了,这就和没设置过滤器时走的$this->runAction ( $action );一样了。
过滤器分析完后,就是什么数据操作之类的,最后是渲染视图render()。这就太简单了,extract($data),然后在include下视图文件就可以了。
还有forward()方法,就是跳转到另一个controller/action,实质就是返回CWebApplication的runController再来一遍上面分析的过程。
最后附上,裁剪的yii http://files.cnblogs.com/TheViper/framework.zip
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号