Heim > Backend-Entwicklung > PHP-Tutorial > Analyse des Yii-Framework-Quellcodes (3)

Analyse des Yii-Framework-Quellcodes (3)

WBOY
Freigeben: 2016-08-08 09:33:28
Original
1192 Leute haben es durchsucht

Bitte geben Sie beim Nachdruck an: TheViper http://www.cnblogs.com/TheViper/

Im vorherigen Artikel ging es um ¥route=$this->getUrlManager ()->parseUrl ($this->getRequest()); in CWebApplication und um $route=controler/actionid.

In diesem Artikel geht es um $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> }
Nach dem Login kopieren

$ca = $this->createController ($route)); Die Funktion von createController besteht darin, den Controller und die Aktion in $route zu trennen und eine Controller-Instanz zu erstellen.

Abschließend werden die Controller-Instanz und die Aktions-ID zurückgegeben.

Gehen Sie dann zurück zu runController($route),$controller->init (); und führen Sie es aus, wenn der Controller initialisiert wird. Dies muss beispielsweise in der Unterklasse neu geschrieben werden:

<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> }    
Nach dem Login kopieren

Auf diese Weise können Sie $this->db verwenden, um die DB-Komponente in VideoController aufzurufen.

$controller->run ($actionID);Übertragung an 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> }
Nach dem Login kopieren

$this->createAction ( $actionID ); Erstellt eine Aktionsinstanz.

Dann runActionWithFilters($action, $filters); wenn kein filter() vorhanden ist, direkt runAction($action).

$action->runWithParams ( $this->getActionParams () ).$action ist eine CInlineAction-Instanz.

<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> }
Nach dem Login kopieren

Aktion

<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> }
Nach dem Login kopieren

Beide Klassen sind sehr einfach, sie führen lediglich die Aktionsmethode in der Controller-Klasse aus.

Zurück zu runActionWithFilters($action, $filters) oben, wenn filter() vorhanden ist, CFilterChain::create ( $this, $action, $filters )->run ();

Wenn ein Filter vorhanden ist, muss die Filterliste natürlich vor dem Ausführen der Aktionsmethode festgelegt werden.

CFilterChain analysiert eine Konfiguration ähnlich „application.filters.LoginFilter upload_video“ in eine Filterkette.

Jedes Element in der Filterkette ist eine CInlineFilter- oder CFilter-Instanz.

<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> }
Nach dem Login kopieren

'application.filters.LoginFilter upload_video' Diese Konfiguration erstellt eine CFilter-Instanz.

<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> }
Nach dem Login kopieren

Dann gibt es run() in CFilterChain::create ($this, $action, $filters)->run (); Wenn die von der Anfrage analysierte Aktion upload_video ist, entfernt Yii die LoginFilter-Instanz.

Zum Beispiel mein 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> ?>
Nach dem Login kopieren

Es gibt ein Präfix und ein Postfix im Inneren, was bedeutet, dass für die Aktionsmethode, die den Filter aktivieren muss, die selbstdefinierten Methoden preFilter und postFilter vor bzw. nach der Ausführung der Aktionsmethode ausgeführt werden.

Dann gibt es $filterChain->run (); hier kann man leicht Fehler machen.

Tatsächlich habe ich run() erneut in CFilterChain verwendet und $this->filterIndex darin bemerkt, was ein bisschen wie eine Rekursion ist.

Wenn der Filter eine Aktion filtern soll, gehen Sie wie folgt zu CFilter, geben Sie dann CFilterChain und $this->filterIndex zurück und fahren Sie dann mit $filterChain->run (); fort. . . . . .

Für mein „application.filters.LoginFilter upload_video“ wird nur die Aktion „upload_video“ gefiltert. Wenn also CFilterChain zurückgegeben wird, ist $this->filterIndex zu 1 geworden und die Filterliste hat nur eine Filterinstanz, also wird es dieses Mal gehen zu $this->controller->runAction ( $this->action );, was dasselbe ist wie $this->runAction ( $action ); wenn kein Filter gesetzt ist.

Nachdem der Filter analysiert wurde, gibt es einige Datenoperationen und dergleichen und schließlich die Rendering-Ansicht render(). Das ist zu einfach: Extrahieren Sie ($ data) und fügen Sie dann die Ansichtsdatei ein.

Es gibt auch die Methode „forward()“, die zu einem anderen Controller/einer anderen Aktion springt. Der Kern besteht darin, zum runController von CWebApplication zurückzukehren und den obigen Analysevorgang zu wiederholen.

Abschließend ist das zugeschnittene yii http://files.cnblogs.com/TheViper/framework.zip beigefügt

Das Obige hat die Analyse des Yii-Framework-Quellcodes (3) vorgestellt, einschließlich des Inhalts des Yii-Framework-Quellcodes. Ich hoffe, dass es für Freunde hilfreich sein wird, die sich für PHP-Tutorials interessieren.

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage