Home > Backend Development > PHP Tutorial > Yii framework source code analysis (3)

Yii framework source code analysis (3)

WBOY
Release: 2016-08-08 09:33:28
Original
1192 people have browsed it

Please indicate when reprinting: TheViper http://www.cnblogs.com/TheViper/

The previous article talked about ¥route=$this->getUrlManager ()->parseUrl ($this->getRequest()); in CWebApplication, and got $route=controler/actionid.

This article talks about $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> }
Copy after login

$ca = $this->createController ($route)); The function of createController is to separate the controller and action in $route and create a controller instance.

Finally, the controller instance and actionid are returned.

Then go back to CWebApplication's runController($route),$controller->init (); and execute it when the controller is initialized. This needs to be rewritten in the subclass, for example:

<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> }    
Copy after login

In this way, you can use $this->db to call the db component in VideoController.

$controller->run ( $actionID );Transfer to 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> }
Copy after login

$this->createAction ( $actionID ); Create an action instance.

Then runActionWithFilters($action, $filters); if there is no filter(), directly runAction($action).

$action->runWithParams ( $this->getActionParams () ).$action is a CInlineAction instance.

<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> }
Copy after login

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> }
Copy after login

Both classes are very simple, they just execute the action method in the controller class.

Return to runActionWithFilters($action, $filters) above; if there is filter(), CFilterChain::create ( $this, $action, $filters )->run ();

Obviously, if there is a filter, the filter list must be set before executing the action method.

CFilterChain parses a configuration similar to 'application.filters.LoginFilter+upload_video' into a filter chain.

Each item in the filter chain is a CInlineFilter or CFilter instance.

<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> }
Copy after login

'application.filters.LoginFilter+upload_video' This configuration will create a CFilter instance.

<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> }
Copy after login

Then there is run() in CFilterChain::create ($this, $action, $filters)->run (); above. If the action parsed into by the request is upload_video, Yii will take out the LoginFilter instance.

For example, my 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> ?>
Copy after login

There is a prefix and a postfix inside, which means that for the action method that needs to enable the filter, the self-defined preFilter and postFilter methods are executed before and after the action method is executed respectively.

Then there's $filterChain->run (); it's easy to make mistakes here.

In fact, I used run() in CFilterChain again and noticed $this->filterIndex++ inside, which is a bit like recursion.

If the filter is to filter an action, go to CFilter like this, then $filterChain->run (); return CFilterChain, and $this->filterIndex++, then continue $filterChain->run ();. . . . . .

For my 'application.filters.LoginFilter+upload_video', only the upload_video action is filtered, so when CFilterChain is returned, $this->filterIndex has become 1, and the filter list has only one filter instance, so this This time it will go to $this->controller->runAction ( $this->action );, which is the same as $this->runAction ( $action ); when no filter is set.

After the filter is analyzed, there are some data operations and the like, and finally the rendering view render(). This is too simple, extract($data), and then include the view file.

There is also the forward() method, which is to jump to another controller/action. The essence is to return to CWebApplication's runController and repeat the above analysis process.

Finally, attached is the cropped yii http://files.cnblogs.com/TheViper/framework.zip

The above has introduced the yii framework source code analysis (3), including the content of the yii framework source code. I hope it will be helpful to friends who are interested in PHP tutorials.

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template