Heim >php教程 >php手册 >yii源码分析2,yii源码分析

yii源码分析2,yii源码分析

WBOY
WBOYOriginal
2016-06-13 09:21:401010Durchsuche

yii源码分析2,yii源码分析

转载请注明:TheViper http://www.cnblogs.com/TheViper/

上一篇主要分析了Yii::createWebApplication ( $config )->run ();的createWebApplication ( $config )部分,这篇分析后面的。

 run()也是不在CWebApplication里面,在CApplication 里。

<span> 1</span> <?<span>php
</span><span> 2</span> <span>abstract</span> <span>class</span> CApplication <span>extends</span><span> CModule {
</span><span> 3</span>     <span>private</span> <span>$_id</span><span>;
</span><span> 4</span>     <span>private</span> <span>$_basePath</span><span>;
</span><span> 5</span>     <span>abstract</span> <span>public</span> <span>function</span><span> processRequest();
</span><span> 6</span>     <span>public</span> <span>function</span> __construct(<span>$config</span> = <span>null</span><span>) {
</span><span> 7</span>         <span>if</span> (<span>is_string</span> ( <span>$config</span><span> ))
</span><span> 8</span>             <span>$config</span> = <span>require</span> (<span>$config</span><span>);
</span><span> 9</span>         Yii::setApplication ( <span>$this</span> );<span>//</span><span>保存整个app实例</span>
<span>10</span>         <span>if</span> (<span>isset</span> ( <span>$config</span> ['basePath'<span>] )) {
</span><span>11</span>             <span>$this</span>->setBasePath ( <span>$config</span> ['basePath'<span>] );
</span><span>12</span>             <span>unset</span> ( <span>$config</span> ['basePath'<span>] );
</span><span>13</span>         } <span>else</span>
<span>14</span>             <span>$this</span>->setBasePath ( 'protected'<span> );
</span><span>15</span>         <span>//</span><span>设置别名,后面就可以用application表示basePath了</span>
<span>16</span>         Yii::setPathOfAlias ( 'application', <span>$this</span>-><span>getBasePath () );
</span><span>17</span>         <span>//</span><span>钩子,模块 预 初始化时执行,子类实现。不过这时,配置还没有写入框架</span>
<span>18</span>         <span>$this</span>-><span>preinit ();
</span><span>19</span>         <span>$this</span>-><span>registerCoreComponents ();
</span><span>20</span>         <span>//</span><span>父类实现</span>
<span>21</span>         <span>$this</span>->configure ( <span>$config</span><span> );
</span><span>22</span>         <span>//</span><span>加载静态应用组件</span>
<span>23</span>         <span>$this</span>-><span>preloadComponents ();
</span><span>24</span>         <span>//</span><span>这才开始初始化模块</span>
<span>25</span>         <span>$this</span>-><span>init ();
</span><span>26</span> <span>    }
</span><span>27</span>     <span>protected</span> <span>function</span><span> registerCoreComponents() {
</span><span>28</span>         <span>$components</span> = <span>array</span><span> (
</span><span>29</span>                 'request' => <span>array</span><span> (
</span><span>30</span>                         'class' => 'CHttpRequest'
<span>31</span>                 ),
<span>32</span>                 'urlManager' => <span>array</span><span> (
</span><span>33</span>                         'class' => 'CUrlManager'
<span>34</span> <span>                )
</span><span>35</span> <span>        );
</span><span>36</span> 
<span>37</span>         <span>$this</span>->setComponents ( <span>$components</span> );<span>//</span><span>父类实现</span>
<span>38</span> <span>    }
</span><span>39</span>     <span>public</span> <span>function</span><span> run() {
</span><span>40</span>         <span>$this</span>-><span>processRequest ();
</span><span>41</span> <span>    }
</span><span>42</span>     <span>public</span> <span>function</span><span> getId() {
</span><span>43</span>         <span>if</span> (<span>$this</span>->_id !== <span>null</span><span>)
</span><span>44</span>             <span>return</span> <span>$this</span>-><span>_id;
</span><span>45</span>         <span>else</span>
<span>46</span>             <span>return</span> <span>$this</span>->_id = <span>sprintf</span> ( '%x', <span>crc32</span> ( <span>$this</span>->getBasePath () . <span>$this</span>-><span>name ) );
</span><span>47</span> <span>    }
</span><span>48</span>     <span>public</span> <span>function</span> setId(<span>$id</span><span>) {
</span><span>49</span>         <span>$this</span>->_id = <span>$id</span><span>;
</span><span>50</span> <span>    }
</span><span>51</span>     <span>public</span> <span>function</span><span> getBasePath() {
</span><span>52</span>         <span>return</span> <span>$this</span>-><span>_basePath;
</span><span>53</span> <span>    }
</span><span>54</span>     <span>public</span> <span>function</span> setBasePath(<span>$path</span><span>) {
</span><span>55</span>         <span>if</span> ((<span>$this</span>->_basePath = <span>realpath</span> ( <span>$path</span> )) === <span>false</span> || ! <span>is_dir</span> ( <span>$this</span>-><span>_basePath ))
</span><span>56</span>             <span>return</span><span>;
</span><span>57</span> <span>    }
</span><span>58</span>     <span>public</span> <span>function</span><span> getDb() {
</span><span>59</span>         <span>return</span> <span>$this</span>->getComponent ( 'db' );<span>//</span><span>父类实现</span>
<span>60</span> <span>    }
</span><span>61</span>     <span>public</span> <span>function</span><span> getUrlManager() {
</span><span>62</span>         <span>return</span> <span>$this</span>->getComponent ( 'urlManager'<span> );
</span><span>63</span> <span>    }
</span><span>64</span>     <span>public</span> <span>function</span><span> getController() {
</span><span>65</span>         <span>return</span> <span>null</span><span>;
</span><span>66</span> <span>    }
</span><span>67</span>     <span>public</span> <span>function</span> getBaseUrl(<span>$absolute</span> = <span>false</span><span>) {
</span><span>68</span>         <span>return</span> <span>$this</span>->getRequest ()->getBaseUrl ( <span>$absolute</span><span> );
</span><span>69</span> <span>    }
</span><span>70</span> }

run()又用了CWebApplication里面的processRequest()。薛强大哥(yii作者),架构要不要这样啊.裁剪后当然觉得这样的调用很没意思。

后面的主要在CWebApplication里了。

<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> }

对于$this->getUrlManager (),YiiBase里面有'CUrlManager' => 'CUrlManager.php'这个映射,说明是实例化了CUrlManager这个类。

 

<span> 1</span> <?<span>php
</span><span> 2</span> <span>class</span><span> CUrlManager {
</span><span> 3</span>     <span>const</span> GET_FORMAT = 'get'<span>;
</span><span> 4</span>     <span>public</span> <span>$rules</span> = <span>array</span><span> ();
</span><span> 5</span>     <span>public</span> <span>$urlSuffix</span> = ''<span>;
</span><span> 6</span>     <span>public</span> <span>$caseSensitive</span> = <span>true</span><span>;
</span><span> 7</span>     <span>public</span> <span>$urlRuleClass</span> = 'CUrlRule'<span>;
</span><span> 8</span>     <span>private</span> <span>$_urlFormat</span> = self::<span>GET_FORMAT;
</span><span> 9</span>     <span>private</span> <span>$_rules</span> = <span>array</span><span> ();
</span><span>10</span>     <span>private</span> <span>$_baseUrl</span><span>;
</span><span>11</span>     <span>protected</span> <span>function</span><span> processRules() {
</span><span>12</span>         <span>//</span><span>遍历自定义的请求匹配规则</span>
<span>13</span>         <span>foreach</span> ( <span>$this</span>->rules <span>as</span> <span>$pattern</span> => <span>$route</span><span> ) {
</span><span>14</span>             <span>//</span><span>对每一个规则创建CUrlRule实例</span>
<span>15</span>             <span>$this</span>->_rules [] = <span>$this</span>->createUrlRule ( <span>$route</span>, <span>$pattern</span><span> );
</span><span>16</span> <span>        }
</span><span>17</span> <span>    }
</span><span>18</span>     <span>protected</span> <span>function</span> createUrlRule(<span>$route</span>, <span>$pattern</span><span>) {
</span><span>19</span>         <span>if</span> (<span>is_array</span> ( <span>$route</span> ) && <span>isset</span> ( <span>$route</span> ['class'<span>] ))
</span><span>20</span>             <span>return</span> <span>$route</span><span>;
</span><span>21</span>         <span>else</span><span> {
</span><span>22</span>             <span>//</span><span>import第二个参数表示是否立即包含类文件。 如果为flase,则类文件仅在被使用时包含。 这个参数仅当使用一个类的路径 别名 时才会用到</span>
<span>23</span>             <span>$urlRuleClass</span> = Yii::import ( <span>$this</span>->urlRuleClass, <span>true</span><span> );
</span><span>24</span>             <span>//</span><span>创建CUrlRule实例</span>
<span>25</span>             <span>return</span> <span>new</span> <span>$urlRuleClass</span> ( <span>$route</span>, <span>$pattern</span><span> );
</span><span>26</span> <span>        }
</span><span>27</span> <span>    }
</span><span>28</span>     <span>//</span><span>类似于__construct()</span>
<span>29</span>     <span>public</span> <span>function</span><span> init() {
</span><span>30</span>         <span>$this</span>-><span>processRules ();
</span><span>31</span> <span>    }
</span><span>32</span>     <span>public</span> <span>function</span> parseUrl(<span>$request</span><span>) {
</span><span>33</span>         <span>//</span><span>获取请求</span>
<span>34</span>         <span>$rawPathInfo</span> = <span>$request</span>-><span>getPathInfo ();
</span><span>35</span>         <span>$pathInfo</span> = <span>$this</span>->removeUrlSuffix ( <span>$rawPathInfo</span>, <span>$this</span>-><span>urlSuffix );
</span><span>36</span>         <span>foreach</span> ( <span>$this</span>->_rules <span>as</span> <span>$i</span> => <span>$rule</span><span> ) {
</span><span>37</span>             <span>if</span> ((<span>$r</span> = <span>$rule</span>->parseUrl ( <span>$this</span>, <span>$pathInfo</span>, <span>$rawPathInfo</span> )) !== <span>false</span><span>) {
</span><span>38</span>                 <span>return</span> <span>$r</span><span>;
</span><span>39</span> <span>            }
</span><span>40</span> <span>        }
</span><span>41</span>         <span>return</span> <span>$pathInfo</span><span>;
</span><span>42</span> <span>    }
</span><span>43</span>     <span>//</span><span>解析请求,将请求参数写入$_REQUEST</span>
<span>44</span>     <span>public</span> <span>function</span> parsePathInfo(<span>$pathInfo</span><span>) {
</span><span>45</span>         <span>if</span> (<span>$pathInfo</span> === ''<span>)
</span><span>46</span>             <span>return</span><span>;
</span><span>47</span>         <span>$segs</span> = <span>explode</span> ( '/', <span>$pathInfo</span> . '/'<span> );
</span><span>48</span>         <span>$n</span> = <span>count</span> ( <span>$segs</span><span> );
</span><span>49</span>         <span>for</span>(<span>$i</span> = 0; <span>$i</span> < <span>$n</span> - 1; <span>$i</span> += 2<span>) {
</span><span>50</span>             <span>$key</span> = <span>$segs</span> [<span>$i</span><span>];
</span><span>51</span>             <span>if</span> (<span>$key</span> === ''<span>)
</span><span>52</span>                 <span>continue</span><span>;
</span><span>53</span>             <span>$value</span> = <span>$segs</span> [<span>$i</span> + 1<span>];
</span><span>54</span>             <span>if</span> ((<span>$pos</span> = <span>strpos</span> ( <span>$key</span>, '[' )) !== <span>false</span> && (<span>$m</span> = <span>preg_match_all</span> ( '/\[(.*?)\]/', <span>$key</span>, <span>$matches</span> )) > 0<span>) {
</span><span>55</span>                 <span>$name</span> = <span>substr</span> ( <span>$key</span>, 0, <span>$pos</span><span> );
</span><span>56</span>                 <span>for</span>(<span>$j</span> = <span>$m</span> - 1; <span>$j</span> >= 0; -- <span>$j</span><span>) {
</span><span>57</span>                     <span>if</span> (<span>$matches</span> [1] [<span>$j</span>] === ''<span>)
</span><span>58</span>                         <span>$value</span> = <span>array</span><span> (
</span><span>59</span>                             <span>$value</span> 
<span>60</span> <span>                            );
</span><span>61</span>                     <span>else</span>
<span>62</span>                         <span>$value</span> = <span>array</span><span> (
</span><span>63</span>                             <span>$matches</span> [1] [<span>$j</span>] => <span>$value</span> 
<span>64</span> <span>                            );
</span><span>65</span> <span>                }
</span><span>66</span>                 <span>if</span> (<span>isset</span> ( <span>$_GET</span> [<span>$name</span>] ) && <span>is_array</span> ( <span>$_GET</span> [<span>$name</span><span>] ))
</span><span>67</span>                     <span>$value</span> = CMap::mergeArray ( <span>$_GET</span> [<span>$name</span>], <span>$value</span><span> );
</span><span>68</span>                 <span>$_REQUEST</span> [<span>$name</span>] = <span>$_GET</span> [<span>$name</span>] = <span>$value</span><span>;
</span><span>69</span>             } <span>else</span><span> {                
</span><span>70</span>                 <span>$_REQUEST</span> [<span>$key</span>] = <span>$_GET</span> [<span>$key</span>] = <span>$value</span><span>;
</span><span>71</span> <span>            }
</span><span>72</span> <span>        }
</span><span>73</span> <span>    }
</span><span>74</span>     <span>//</span><span>去除请求后缀,如video/broadcast.html=>video/broadcast </span>
<span>75</span>     <span>public</span> <span>function</span> removeUrlSuffix(<span>$pathInfo</span>, <span>$urlSuffix</span><span>) {
</span><span>76</span>         <span>if</span> (<span>$urlSuffix</span> !== '' && <span>substr</span> ( <span>$pathInfo</span>, - <span>strlen</span> ( <span>$urlSuffix</span> ) ) === <span>$urlSuffix</span><span>)
</span><span>77</span>             <span>return</span> <span>substr</span> ( <span>$pathInfo</span>, 0, - <span>strlen</span> ( <span>$urlSuffix</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> }

yii在创建组件的时候,在调用了CModule的getComponent($id, $createIfNull = true)里面调用了$component->init ();。

所以这里进入init(),然后processRules()遍历自定义的请求匹配规则。如

<span> 1</span>                 'urlManager' => <span>array</span><span> (
</span><span> 2</span>                         'urlFormat' => 'path',
<span> 3</span>                         'rules' => <span>array</span><span> (
</span><span> 4</span>                                 'comment_reply/<a:\d+>/<ci:\d+>' => 'reply/load_comment_reply',
<span> 5</span>                                 'b/<id:\d+>' => <span>array</span><span> (
</span><span> 6</span>                                         'video/broadcast',
<span> 7</span>                                         'urlSuffix' => '.html' 
<span> 8</span>                                 ),
<span> 9</span>                                 'c/<list_start:\d+>' => 'video/list_more_video',
<span>10</span>                                 'u/reg' => 'user/reg',
<span>11</span>                                 'v/upload' => 'video/upload_video',
<span>12</span>                                 'login' => 'user/to_login',
<span>13</span>                                 'show_chanel/<chanel_id:\d+>' => 'show/chanel' ,
<span>14</span>                                 'show/<show_id:\d+>' => 'show/show',
<span>15</span> <span>                        ) 
</span><span>16</span>                 ) 

 $this->_rules [] = $this->createUrlRule ( $route, $pattern );对每一个规则创建CUrlRule实例,并保存。

<span> 1</span> <?<span>php
</span><span> 2</span> <span>class</span><span> CUrlRule {
</span><span> 3</span>     <span>public</span> <span>$urlSuffix</span><span>;
</span><span> 4</span>     <span>public</span> <span>$defaultParams</span> = <span>array</span><span> ();
</span><span> 5</span>     <span>public</span> <span>$route</span><span>;
</span><span> 6</span>     <span>public</span> <span>$routePattern</span><span>;
</span><span> 7</span>     <span>public</span> <span>$pattern</span><span>;
</span><span> 8</span>     <span>public</span> <span>$template</span><span>;
</span><span> 9</span>     <span>public</span> <span>$params</span> = <span>array</span><span> ();
</span><span>10</span>     <span>//</span><span>根据自定义规则构建匹配参数的正则表达式。</span>
<span>11</span>     <span>public</span> <span>function</span> __construct(<span>$route</span>, <span>$pattern</span><span>) {
</span><span>12</span>         <span>if</span> (<span>is_array</span> ( <span>$route</span><span> )) {
</span><span>13</span>             <span>foreach</span> ( <span>array</span><span> (
</span><span>14</span>                     'urlSuffix',
<span>15</span>                     'caseSensitive',
<span>16</span>                     'defaultParams',
<span>17</span>             ) <span>as</span> <span>$name</span><span> ) {
</span><span>18</span>                 <span>if</span> (<span>isset</span> ( <span>$route</span> [<span>$name</span><span>] ))
</span><span>19</span>                     <span>$this</span>-><span>$name</span> = <span>$route</span> [<span>$name</span><span>];
</span><span>20</span> <span>            }
</span><span>21</span>             <span>if</span> (<span>isset</span> ( <span>$route</span> ['pattern'<span>] ))
</span><span>22</span>                 <span>$pattern</span> = <span>$route</span> ['pattern'<span>];
</span><span>23</span>             <span>$route</span> = <span>$route</span> [0<span>];
</span><span>24</span> <span>        }
</span><span>25</span>         <span>$this</span>->route = <span>trim</span> ( <span>$route</span>, '/'<span> );
</span><span>26</span>         
<span>27</span>         <span>$tr2</span> ['/'] = <span>$tr</span> ['/'] = '\\/'<span>;
</span><span>28</span>         <span>$tr</span> ['.'] = '\\.'<span>;
</span><span>29</span>         
<span>30</span>         <span>$this</span>->hasHostInfo = ! <span>strncasecmp</span> ( <span>$pattern</span>, 'http://', 7 ) || ! <span>strncasecmp</span> ( <span>$pattern</span>, 'https://', 8<span> );
</span><span>31</span>         
<span>32</span>         <span>if</span> (<span>preg_match_all</span> ( '/<(\w+):?(.*?)?>/', <span>$pattern</span>, <span>$matches</span><span> )) {
</span><span>33</span>             <span>$tokens</span> = <span>array_combine</span> ( <span>$matches</span> [1], <span>$matches</span> [2<span>] );
</span><span>34</span>             <span>foreach</span> ( <span>$tokens</span> <span>as</span> <span>$name</span> => <span>$value</span><span> ) {
</span><span>35</span>                 <span>if</span> (<span>$value</span> === ''<span>)
</span><span>36</span>                     <span>$value</span> = '[^\/]+'<span>;
</span><span>37</span>                 <span>$tr</span> ["<<span>$name</span>>"] = "(?P<<span>$name</span>><span>$value</span>)"<span>;
</span><span>38</span>                 <span>//</span><span>取出自定义规则中隐藏的参数,保存</span>
<span>39</span>                 <span>if</span> (<span>isset</span> ( <span>$this</span>->references [<span>$name</span><span>] ))
</span><span>40</span>                     <span>$tr2</span> ["<<span>$name</span>>"] = <span>$tr</span> ["<<span>$name</span>>"<span>];
</span><span>41</span>                 <span>else</span>
<span>42</span>                     <span>$this</span>->params [<span>$name</span>] = <span>$value</span><span>;
</span><span>43</span> <span>            }
</span><span>44</span> <span>        }
</span><span>45</span>         <span>$p</span> = <span>rtrim</span> ( <span>$pattern</span>, '*'<span> );
</span><span>46</span>         <span>$this</span>->append = <span>$p</span> !== <span>$pattern</span><span>;
</span><span>47</span>         <span>$p</span> = <span>trim</span> ( <span>$p</span>, '/'<span> );
</span><span>48</span>         <span>$this</span>->template = <span>preg_replace</span> ( '/<(\w+):?.*?>/', '<$1>', <span>$p</span><span> );
</span><span>49</span>         <span>$this</span>->pattern = '/^' . <span>strtr</span> ( <span>$this</span>->template, <span>$tr</span> ) . '\/'<span>;
</span><span>50</span>         <span>//</span><span>合成匹配的正则表达式</span>
<span>51</span>         <span>if</span> (<span>$this</span>-><span>append)
</span><span>52</span>             <span>$this</span>->pattern .= '/u'<span>;
</span><span>53</span>         <span>else</span>
<span>54</span>             <span>$this</span>->pattern .= '$/u'<span>;
</span><span>55</span> <span>    }
</span><span>56</span>     <span>//</span><span>根据正则表达式和请求,将隐藏参数与请求参数一一匹配,保存$_REQUEST</span>
<span>57</span>     <span>public</span> <span>function</span> parseUrl(<span>$manager</span>, <span>$pathInfo</span>, <span>$rawPathInfo</span><span>) {
</span><span>58</span>         <span>if</span> (<span>$this</span>->urlSuffix !== <span>null</span><span>) {
</span><span>59</span>             <span>$pathInfo</span> = <span>$manager</span>->removeUrlSuffix ( <span>$rawPathInfo</span>, <span>$this</span>-><span>urlSuffix );
</span><span>60</span> <span>        }
</span><span>61</span>         <span>$pathInfo</span> .= '/'<span>;
</span><span>62</span>         <span>if</span> (<span>preg_match</span> ( <span>$this</span>->pattern, <span>$pathInfo</span>, <span>$matches</span><span> )) {
</span><span>63</span>             <span>foreach</span> ( <span>$this</span>->defaultParams <span>as</span> <span>$name</span> => <span>$value</span><span> ) {
</span><span>64</span>                 <span>if</span> (! <span>isset</span> ( <span>$_GET</span> [<span>$name</span><span>] ))
</span><span>65</span>                     <span>$_REQUEST</span> [<span>$name</span>] = <span>$_GET</span> [<span>$name</span>] = <span>$value</span><span>;
</span><span>66</span> <span>            }
</span><span>67</span>             <span>$tr</span> = <span>array</span><span> ();
</span><span>68</span>             <span>foreach</span> ( <span>$matches</span> <span>as</span> <span>$key</span> => <span>$value</span><span> ) {
</span><span>69</span>                 <span>if</span> (<span>isset</span> ( <span>$this</span>->references [<span>$key</span><span>] ))
</span><span>70</span>                     <span>$tr</span> [<span>$this</span>->references [<span>$key</span>]] = <span>$value</span><span>;
</span><span>71</span>                 <span>elseif</span> (<span>isset</span> ( <span>$this</span>->params [<span>$key</span><span>] ))
</span><span>72</span>                     <span>$_REQUEST</span> [<span>$key</span>] = <span>$_GET</span> [<span>$key</span>] = <span>$value</span><span>;
</span><span>73</span> <span>            }
</span><span>74</span>             <span>if</span> (<span>$pathInfo</span> !== <span>$matches</span> [0]) <span>//</span><span>如果还有另外的请求参数</span>
<span>75</span>                 <span>$manager</span>->parsePathInfo ( <span>ltrim</span> ( <span>substr</span> ( <span>$pathInfo</span>, <span>strlen</span> ( <span>$matches</span> [0] ) ), '/'<span> ) );
</span><span>76</span>             <span>return</span> <span>$this</span>-><span>route;
</span><span>77</span>         } <span>else</span>
<span>78</span>             <span>return</span> <span>false</span><span>;
</span><span>79</span> <span>    }
</span><span>80</span> }

CUrlRule中的parseUrl($manager, $pathInfo, $rawPathInfo)这里暂时还没用到。

然后回到CWebApplication中的¥route=$this->getUrlManager ()->parseUrl ($this->getRequest());。后面parseUrl开始解析请求了。

转到CUrlManager的parseUrl($request),遍历创建CUrlRule过程中保存的匹配规则,再在CUrlRule里面用CUrlRule的parseUrl($manager, $pathInfo, $rawPathInfo)将隐藏参数与请求参数一一匹配,保存$_REQUEST.

比如:

'b/' => array (
  'video/broadcast',
  'urlSuffix' => '.html'
)

我的请求是b/1.html,就会被解析成video/broadcast?id=1.而最终的$route就是这个。

Stellungnahme:
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